From: David Ching on 23 Jun 2010 17:13 "JRGlide" <JRGlide(a)discussions.microsoft.com> wrote in message news:EEB5EE8A-1F6A-4C3C-9473-045EBB640787(a)microsoft.com... > Thank you. You are right that MATLAB loads a DLL and then calls another > DLL > which displays the data. In case it matters, the viewing program is an > application that I converted into a DLL, so it has its own CWinApp, menus, > CView, etc. In fact, you may have been the one who helped me develop it > several years ago. > > My question about your approach is that I alway read on this forum that > the > GUI should always be in the application and never in a thread - that only > processing should be done is a separate thread. So why is this different? > It is a good general rule to keep all UI on the main thread. But it is safe to create and access additional windows on a separate thread. This is especially true in this case where the MATLAB window is disabled while yours is active, so there is no chance the user can simultanously mix the two. The rule is the window must be accessed only from the thread it is created in. In the new thread, make sure you init OpenGL and OLE if necessary. -- David
From: David Ching on 23 Jun 2010 17:20 "David Ching" <dc(a)remove-this.dcsoft.com> wrote in message news:8438CB1A-C21F-4A9E-9950-D3E4822D9D8D(a)microsoft.com... > It is a good general rule to keep all UI on the main thread. But it is > safe to create and access additional windows on a separate thread. This > is especially true in this case where the MATLAB window is disabled while > yours is active, so there is no chance the user can simultanously mix the > two. The rule is the window must be accessed only from the thread it is > created in. In the new thread, make sure you init OpenGL and OLE if > necessary. > Oops, I guess your window and MATLAB will be active simultaneously, which is the whole point of this! ;) So you will have both MATLAB's and your thread's message pumps dispatching messages simultaneously. This should be OK. In your exported function, if it finds the thread and window already created, I would post messages to your window to pass the new graphing parameters, rather than access it the window directly. Also, you may need to add code in DllMain() so when the process detaches, you close the window and exit the thread, since MATLAB won't know to clean up these. If you do nothing, Windows will of course destroy your window and unload your DLL anyway, but I don't know how cleanly. -- David
From: Hector Santos on 23 Jun 2010 18:10 In principle, each thread that wishes to have its own GUI needs a message queue processor to pump messages to the controls. Every EXE has a main thread and every GUI EXE has a message queue associated with the main thread to draw things. So if you have secondary threads to do background processing, in my design experience there were two safe ways to pass "data" that is going to be drawn in the main thread GUI window: 1) Using SendMessage/PostMessage: The secondary thread calls SendMessage() (send/wait) or PostMessage() (send/no wait) to the Main thread Message Queue. Here you have to create some "buffer" to pass via the Send/PostMessage(). If you call SendMessage() which is a SEND/WAIT for completion, you can pass a pointer to the local buffer and use it in the main thread because it will still be "alive" when the main thread gets it. If you call PostMessage() which is a SEND/NO WAIT, then here you are queuing the message in main thread message queue to be processed when the main thread message pump gets to it at some delayed time. So here, you need to pass a new allocated buffer pointer that the eventual main thread processing will release. 2) Using a common shared Data Structure. Here you prepare a common (GLOBAL) data structure filled with fields and information that: 1) The secondary thread fills (WRITE) 2) The main thread via a TIMER or a "WAKE UP" event will READ data structure to update "refresh" the screen. Here you need to synchronize using locks (semaphores, mutexes, etc) the WRITE/READ of the shared common resource (data structure) to prevent potential clobbering of data. For example, lets say you want to data points in the main form window. Counter1: ________ << member controls m_Counter1 Counter2: ________ << member controls m_Counter2 That is updated per threads: typedef struct _tagCommonData { int data1; int data2; } COMMONDATA; The easiest lock and guaranteed to be CORRECT and SAFE is a Critical Section but it also the least efficient (speed wise) because its a mutual exclusive READ or WRITE only operation, never two threads can access it at the same time which is possible with a concept called ReaderWriter Locks. ReaderWriter are easy if you get the proper class from some library. So you create a global data and critical section: COMMONDATA globalData = {0}; CCriticalSection csLock(); Now in your secondary threads, your lock and write to the structure: MyThread1() { csLock.Lock(0); globalData.data1++; csLock.Unlock(); } MyThread2() { csLock.Lock(0); globalData.data2++; csLock.Unlock(); } Now in your main program, you add a OnTimer() lets say for evert 100 milliseconds. MyMainWindow::onTimer() { csLock.Lock(0); m_Counter1 = data1; m_Counter2 = data2; csLock.Unlock(); } You can add some efficiency ideas by only updating if dirty: MyMainWindow::onTimer() { csLock.Lock(0); if (m_Counter1 != globalData.data1) m_Counter1 = globalData.data1; if (m_Counter2 != globalData.data2) m_Counter2 = globalData.data2; csLock.Unlock(); } Instead of a timer, you can consider using a signal like a custom registered WM_MY_REFRESH message that will call a OnMyRefresh() message handler in your MyMainWindow to do the screen updating. This makes it more dynamic if there aren't tons of updating going on. A Reader/Writer lock allows you to add logic like a Writer Thread puts a lock on ALL allowing only One writer at a time, but you can have Multiple Readers as long as they are no active writers. So this an more efficient than a Critical Section. So the child threads will enable a Writer Lock: MyThread2() { csReaderWriter.Write(); globalData.data2++; csReaderWriter.Unlock(); } and the main thread will use a Reader Lock: MyMainWindow::onTimer() { csReaderWriter.Reader(); if (m_Counter1 != globalData.data1) m_Counter1 = globalData.data1; if (m_Counter2 != globalData.data2) m_Counter2 = globalData.data2; csReaderWriter.Unlock(); } The above reader/writer lock example is pseudo code, I don't see a MFC based Reader/Writer class but there are many in the public domain. Finally, if you want the child threads to have their own GUI, then the same and only requirement is that the thread has own message pump. The same "Inter Thread" communications apply here as with dealing with the main thread only. -- HLS JRGlide wrote: > Thank you. You are right that MATLAB loads a DLL and then calls another DLL > which displays the data. In case it matters, the viewing program is an > application that I converted into a DLL, so it has its own CWinApp, menus, > CView, etc. In fact, you may have been the one who helped me develop it > several years ago. > > My question about your approach is that I alway read on this forum that the > GUI should always be in the application and never in a thread - that only > processing should be done is a separate thread. So why is this different? > > > "David Ching" wrote: > >> It sounds like MATLAB loads your DLL and calls an exported function which >> shows the 3D window. And when user closes the window, only then does the >> exported function return to MABLAB. So MATLAB waits for your exported >> function to return before allowing any more interaction with the main MATALB >> window. >> >> If so, why don't you alter your exported function to create a new thread >> that shows the 3D window and returns immediately? Then MATLAB and the 3D >> window function simultaneously. The next time MATLAB calls your exported >> function, you check if the thread/3D window already appear and pass the new >> graph data to the window, if so. >> >> -- David >> >> >> "JRGlide" <JRGlide(a)discussions.microsoft.com> wrote in message >> news:75C5F17D-92D6-465A-97DE-50B741907E58(a)microsoft.com... >>> I currently have a MATLAB mex function that allows the user to view & >>> manipulate 3D point cloud data directly from MATLAB. A mex function is >>> nothing more than a standard dll with a specific MATLAB entry point. The >>> viewer was written in MFC using OpenGL. >>> >>> My problem is that since it is a dll the user must close the viewer before >>> returning to MATLAB. In other words, the user calls the viewer from >>> MATLAB, >>> looks at the data, closes the viewer and then returns to MATLAB. >>> >>> I would like to find a way to keep the viewer up permanently so that it >>> works independently from MATLAB so they can both be run at once. What I >>> envision is that MATLAB would call another mex function (or dll) with the >>> data for display. This function would check to see if the viewer is >>> active >>> and activate it if necessary. It would then pass the data to the viewer >>> using some sort of handshake and then return to MATLAB without the viewer >>> disappearing at it does now. If the user changed the data it would make >>> the >>> same call and the dll would update the data in the viewer. >>> >>> My question is that I'm not sure how to go about doing this: >>> >>> 1. I suspect that to do this, the viewer would need to be a regular >>> executable with some sort of interface and not a dll, but maybe I assume >>> wrong. >>> >>> 2. It would first have to know if the viewer is loaded or not and the >>> load >>> it. >>> >>> 3. I'm not sure what the handshake would be between the mex function and >>> the viewer. The data could potentially be hundreds of megs in size. Is >>> there a way I can do that through shared memory or some sort of global >>> memory >>> pool? I'm trying to keep from writing the data to disk and read it back >>> again. Having said that, if I have to limit the data size to say, less >>> than >>> 50 meg, I can live with that. >>> >>> 4. As far as closing the viewer, I guess that would be up to the user >>> after >>> they are finished, just like any other application. >>> >>> Thank you for your help. >>> >> >>
From: JRGlide on 23 Jun 2010 18:22 Thank you everyone for your answers. I have lots to think about now, but at least I know it can be done, which is the first hurdle. As for Joe's question about unloading the DLL, it is partly a MATLAB issue and partly my design flaw. Here is the data flow: *************** ************** ************* * * * * * * * MATLAB * --> * mex function * --> * 3D Viewer * * * * * * * *************** ************** ************* Since the mex function is a DLL, MATLAB will not return until the mex function returns. But I also implemented the viewer as another DLL, so the mex function does not return until the viewer also returns. But if I convert the viewer to an exe and implement the handshake people have suggested, then I hope that it will stay resident. As far as ActiveX as Joe suggested, that was going to be a future question! I read about it once and it didn't sound easy. MATLAB supports ActiveX controls, which might be nice within a MATLAB GUI. As for the data format, the data is simple (x,y,z) floating point data so the data passing is simple. However, I missed my memory estimates by about a factor of 10! I can't see anyone wanting to pass in more than a million points, which is 36 MB of data, so it shouldn't be in the 100's like I said. Then again, no matter what capabilities this has, the engineers always want more!
From: JRGlide on 23 Jun 2010 18:22 I was afraid that the formatting might not come out right. I guess I'll never try that again...
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 Prev: CIPAddressCtrl: focus handle Next: How to embed a word document in CView |