15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


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 Finnigan 

Mike,

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.




| Вернуться в корень Архива |