Beginner's Question about Threading

G

Guest

I'm creating a WinForms app that will act as a companion (think administrator
functionality) to a Pocket PC app. Generally the WinForms app works under
just the UI thread. But if a Pocket PC connects to the desktop via
ActiveSync then a separate thread is spawned.

In addition to the main desktop app window I also have a Notification form
that appears in the lower right of the screen and provides feedback to the
user about what is happening during the Data Transfer process. At first I
instantiated this small form from the Data Transfer thread but then read
several articles and decided to also instantiate it from the UI thread.

I was having all kinds of problems sending update messages from the Data
Transfer thread to the Notification form but did some more reading and
realized that I was breaking the primary threading rule about updating a
control only from the thread where it was created. From my reading I created
methods inside the Notification form class that look like this:


private delegate void ShowStatusDelegate(string text);
public void ShowStatus(string text)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new ShowStatusDelegate(ShowStatus), new object[]
{text});
return;
}

// Only reaches here when on UI thread
labelStatus.Text = text;
Application.DoEvents();
}



I have two immediate questions:

1. Does the code in this method look correct and "solid" ?

2. Do I need the "Application.DoEvents()" line or is it unnecessary?
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

You should not need to call DoEvents() , nor need to use BeginInvoke , a
simple Invoke will do in this case.

Cheers,
 
G

Guest

Ignacio,

Does the rest of the code look okay to you?

In my reading, it was generally recommended to use BeginInvoke to make it
asynchronous whereas Invoke would block until the message was posted. Or is
this not the case?

--
Robert W.
Vancouver, BC
www.mwtech.com



Ignacio Machin ( .NET/ C# MVP ) said:
Hi,

You should not need to call DoEvents() , nor need to use BeginInvoke , a
simple Invoke will do in this case.

Cheers,

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation



Robert W. said:
I'm creating a WinForms app that will act as a companion (think
administrator
functionality) to a Pocket PC app. Generally the WinForms app works under
just the UI thread. But if a Pocket PC connects to the desktop via
ActiveSync then a separate thread is spawned.

In addition to the main desktop app window I also have a Notification form
that appears in the lower right of the screen and provides feedback to the
user about what is happening during the Data Transfer process. At first I
instantiated this small form from the Data Transfer thread but then read
several articles and decided to also instantiate it from the UI thread.

I was having all kinds of problems sending update messages from the Data
Transfer thread to the Notification form but did some more reading and
realized that I was breaking the primary threading rule about updating a
control only from the thread where it was created. From my reading I
created
methods inside the Notification form class that look like this:


private delegate void ShowStatusDelegate(string text);
public void ShowStatus(string text)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new ShowStatusDelegate(ShowStatus), new object[]
{text});
return;
}

// Only reaches here when on UI thread
labelStatus.Text = text;
Application.DoEvents();
}



I have two immediate questions:

1. Does the code in this method look correct and "solid" ?

2. Do I need the "Application.DoEvents()" line or is it unnecessary?
 
G

Guest

FYI - you might want to watch for any replies to my posted question "Firing
cross thread events"

I typically have my worker threads pass status & data to my GUI threads via
custom lightning bolt events...

However be careful when firing your event across threads. If the recipient
of the event is any derivative of the Control class - including a Form - then
the recipient's window handle MUST be valid when you Invoke or else your
worker thread will throw an "invalid window handle" exception...
 
G

Guest

Richard,

One thing I know is an ABSOLUTE fact is that you can use 'InvokeRequired' to
test whether or not you can safely execute the "regular" code in a method.
If 'InvokeRequired' returns {True} then you can NOT excecute the code
directly but must use 'Invoke' or 'BeginInvoke'.

--
Robert W.
Vancouver, BC
www.mwtech.com



Richard said:
FYI - you might want to watch for any replies to my posted question "Firing
cross thread events"

I typically have my worker threads pass status & data to my GUI threads via
custom lightning bolt events...

However be careful when firing your event across threads. If the recipient
of the event is any derivative of the Control class - including a Form - then
the recipient's window handle MUST be valid when you Invoke or else your
worker thread will throw an "invalid window handle" exception...


Robert W. said:
I'm creating a WinForms app that will act as a companion (think administrator
functionality) to a Pocket PC app. Generally the WinForms app works under
just the UI thread. But if a Pocket PC connects to the desktop via
ActiveSync then a separate thread is spawned.

In addition to the main desktop app window I also have a Notification form
that appears in the lower right of the screen and provides feedback to the
user about what is happening during the Data Transfer process. At first I
instantiated this small form from the Data Transfer thread but then read
several articles and decided to also instantiate it from the UI thread.

I was having all kinds of problems sending update messages from the Data
Transfer thread to the Notification form but did some more reading and
realized that I was breaking the primary threading rule about updating a
control only from the thread where it was created. From my reading I created
methods inside the Notification form class that look like this:


private delegate void ShowStatusDelegate(string text);
public void ShowStatus(string text)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new ShowStatusDelegate(ShowStatus), new object[]
{text});
return;
}

// Only reaches here when on UI thread
labelStatus.Text = text;
Application.DoEvents();
}



I have two immediate questions:

1. Does the code in this method look correct and "solid" ?

2. Do I need the "Application.DoEvents()" line or is it unnecessary?
 
B

Brian Gideon

Robert,

You are correct. I think BeginInvoke might be better in your case. If
you use Invoke then your worker thread will block until the UI has
finished processing the message. That means the worker thread will
have to wait until all other queued messages are processed as well.

Brian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top