Worker Threads...
Mike -- irvinm@dialogic.com Wednesday, January 10, 1996 Good day everyone, My question is pretty simple, but I don't see an easy way for me to solve it. Basically, I setup a menu selection which spawns off 10 threads (AFXBeginThread) and each of these threads will update a Static Control (TEXT) on the screen of a CFrameWnd. The problem I am having is that I don't seem to be able to do a SendDlgItemMsg [WM_SETTEXT] (I don't have the code with me) to the Static control from outside the CFrameWnd. I have tried passing "this" to the threads and using it for the command, but nothing happens. I way I solved it (which I really don't like) is to use some global data and have each of the threads update the information there. Then, a timer is used on an interval to update the screen with the global information. Any comments or suggestions would be appreciated. Thanks in advance, MCI -- ------------------------------------------------------------------ | <_o~\ |Michael C. Irvin - M.Irvin@Dialogic.com | | | __\ /\__ |Software Engineer - Dialogic Corporation | /\ | | \\ \---/ | |Steel \//\ | | \\ \-/ |Go Penn State! (Outback bowl winners) | /\\/ | | \\ / |Go Steelers! (AFC Division Champions) | \/ | | \/ |Go Penguins! (Soon to be Champions) | | ------------------------------------------------------------------
John W. Podlogar Jr. -- podlogar@telerama.lm.com Thursday, January 11, 1996 [Mini-digest: 8 responses] On Wed, 10 Jan 1996, Irvin, Mike wrote: > Good day everyone, > > My question is pretty simple, but I don't see an easy way for me > to solve it. Basically, I setup a menu selection which spawns > off 10 threads (AFXBeginThread) and each of these threads will > update a Static Control (TEXT) on the screen of a CFrameWnd. > > The problem I am having is that I don't seem to be able to > do a SendDlgItemMsg [WM_SETTEXT] (I don't have the code with me) to > the Static control from outside the CFrameWnd. I have tried passing > "this" to the threads and using it for the command, but nothing > happens. > > I way I solved it (which I really don't like) is to use some > global data and have each of the threads update the information > there. Then, a timer is used on an interval to update the screen > with the global information. > > Any comments or suggestions would be appreciated. > > Thanks in advance, > MCI You need to create these threads with a class that is derived from CWinThread. As part of this you need to override some of the CWinThread member functions. See the Technical Note in MSVC 4.0 called "Multithreading: Creating User-Interface Threads". This outlines everything you should need to do. I have an app that is similiar to yours and I did it this way and it works great. -John John W. Podlogar Jr. The wise man doesn't pose the right answers, podlogar@lm.com he asks the right questions. http://www.lm.com/~podlogar -----From: James FinniganMike, I just finished implementing some OLE Automation Server that required something very similar to what you are needing. You can generate your ow= n CTimer class that contains all the necessary information you want to stor= e for each thread, including the threadid. Add the object to a collection = class and when you are ready to use it in your thread, sift thru the collection class looking for the same threadid that you stuffed away = in the CTimer class. Voila! Your information is ready to go. This of cour= se is a simple yet robust approach to your problem. No rocket science here = but at least it works. jaf@xilinx.com -----From: Jim Beveridge Irvin, Mike wrote: All of the MFC classes are thread specific. If you do GetDlgItem from a member function of a CDialog-derived class, then the pointer that it returns is only valid for that thread. You need to pass actual window handles and then rebuild the MFC structure using something like the Attach() member function. Hope this helps, Jim -----From: Brad Wilson Did you start a user interface thread or a worker thread? See the MFC technote titled "Multithreading: Creating User-Interface Threads" if you need it. :-) >> I have tried passing >> "this" to the threads and using it for the command, but nothing >> happens. I don't know if the CWnd class is thread-safe, so instead of passing the this pointer, you may want to pass the HWND (which is global) and create a new CWnd object inside the thread to do your work. Good luck! Brad -- class CBradWilson : public CWorldWatchProgrammingTeam { public: CString GetInetAddr() { return CString("bradw@exptech.com"); } CString GetPhone() { return CString("+1 (810) 620-9803"); } CString GetURL() { return CString("http://www.exptech.com"); } CString GetDisclaimer() { return CString("All I say is fact :-p"); } }; "Money is the living power that dies without its root. Money will not serve the mind that cannot match it. Is this the reason why you call it evil?" -----From: Mario Contestabile You will probably have to send a WM_GETTEXT explicitly because of the way SendDlgItemMsg() and GetWindowText() are optimized. HWND OtherEdit; char Buffer[256]; SendMessage(OtherEdit, WM_GETTEXT, sizeof(Buffer), (LPARAM)Buffer); mcontest@universal.com -----From: Marty Fried I assume you are using the version of AfxBeginThread() that looks like: CWinThread* AfxBeginThread( AFX_THREADPROC pfnThreadProc, LPVOID pParam, ... If so, can I also assume that by "passing this to the threads", you mean passing it as the pParam (2nd parameter)? I've used that method to give the thread access to certain class functions, and it worked fine. Then again, if the dialog window handle is in scope for the thread, it should be able to access the control, I would think. Is it possible you might be jumping to the wrong conclusion? (or is it me? ) +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Marty Fried (mfried@linex.com) Marin County, California -----From: mikeblas@interserv.com >My question is pretty simple, but I don't see an easy way for me >to solve it. Basically, I setup a menu selection which spawns >off 10 threads (AFXBeginThread) and each of these threads will >update a Static Control (TEXT) on the screen of a CFrameWnd. Wow! _Ten_ threads! Are you doing a whole buttload of I/O, or are you writing this for a sixteen-processor system? >The problem I am having is that I don't seem to be able to >do a SendDlgItemMsg [WM_SETTEXT] (I don't have the code with me) to >the Static control from outside the CFrameWnd. If you don't want me to explain why your design is really bad, and just want to hear the answer, skip to the next resply paragraph. First, I don't know what you're doing. But having ten threads get kicked off in response to a menu item sounds like you have a really crazy design. I wouldn't be surprised if it took over 100ms, even on a quick machine, to get all of those puppies running! Second, having all of these threads _send_ messages back to the main window completely defeats _ANY_ gain you could have hoped to get from having multiple threads. Let's call your main thread ThreadM, and all of your worker threads Thread0 through Thread9. It sounds like ThreadM sits around and talks with the user all the time. It's responsible for painting as well as receiving input. And Threads0 through Thread9 are off doing the devil's work, which apparently requires ten usually-idle hands. But when one of the worker threads decides to send a message to the window owned by ThreadM, the sending thread blocks until ThreadM processes the message and returns! This means that Thread0 through Thread9 are sitting around blocking while ThreadM busts its butt to service the other threads _and_ the user. In other words, you're doing a lot of extra work in your program to switch thread contexts and it isn't getting you any more work done. You're doing lots of work as a programmer, too, to get all of these threads cooperating. But you're not making a program that's really much faster even after spending all this effort. Sorry to sound soap boxy, but you _did_ say "any comments"! >I have tried passing >"this" to the threads and using it for the command, but nothing >happens. I'm not sure I understand what you mean. "this" what? The static control? The form view? The main thread? To answer your question, I'll need to understand how you're making the SendDlgItemMessage() call. Are you using the MFC member function to do it? If that's true, then that's most likely the problem. The pointer that you've passed to the worker threads is not valid in the context of those threads. You should pass the m_hWnd and then do an Attach() on a new CFormView object back in the worker threads. >I way I solved it (which I really don't like) is to use some >global data and have each of the threads update the information >there. Then, a timer is used on an interval to update the screen >with the global information. That's one approach. Another would be to actualy do some snychronization work between the main thread of your application (or a subordinate user interface thread) and all of these worker threads. You could MsgWaitForMultipleObjects() in a Run() override, or you could use a timeout of zero in PreTranslateMessage(). Let me leak one of the best points (just ask me) from the second edition of my book: When you program with threads, you need to learn to let the threads communicate by using data instead of by using the flow of control. Somehow, when we program single-threadded applications, we begin to think that we have to call or send or return to get something done. Setting a flag that some other flag waits for is a far more practical way to communicate across threads. >| \\ / |Go Steelers! (AFC Division Champions) | \/ | It turns out that I'm not Mike Blaszczak. I'm actually Kevin Green. I just do this computer stuff during the week; I play ball on Saturdays and Sundays. I'm sorry for deceiving everyone. .B ekiM -- TCHAR szDisc[] = _T("These words are my own; I do not speak for Microsoft."); -----From: Niels Ull Jacobsen You can't pass CWnd's between threads as the CWnd-> window mapping is thread-local. You can pass window handles and use CWnd::FromHandle to get a CWnd, however. You could also just pass each thread a handle to the static control and let it do a ::PostMessage(hStatic, WM_SETTEXT, 0, pszText); -- Niels Ull Jacobsen, Kruger A/S Everything stated herein is THE OFFICIAL POLICY of the entire Kruger group and should be taken as legally binding in every respect. Pigs will grow wings and fly.
| Вернуться в корень Архива |