Worker threads interacting with a form

S

Scott Gifford

Hello,

I have a few questions about worker threads interacting with a form.
I'm developing in C# using .NET 2.0 Compact Framework, on the Windows
Mobile platform. I'm using the Visual Studio 2008 beta, but I don't
think any of this question is specific to VS2008.

I know that to interact with a form, the background thread must use
form.Invoke() to call a method in the GUI thread to interact with any
controls. On the compact framework, I cannot send arguments with
Invoke(), so I've been using global variables to communicate this.
For example, if I have a label named "lblStatus", I would create a
corresponding string "newStatus" then write a small method like this:

private void FormUpdateStatus(object sender, EventArgs e)
{
lock (this)
{
if (newStatus != null) {
lblStatus.Text = newStatus;
newStatus = null;
}
}
}

Then from the background thread, I would call a method like this:

public void ThreadUpdateStatus(string s)
{
try
{
lock (this)
{
newStatus = s;
}
this.Invoke(new EventHandler(UpdateStatus));
}
catch (ObjectDisposedException)
{
// Do nothing
}
}

First, I was wondering if this is the best way to approach this, or if
there's a better (or more standard) way to handle this situation,
which must be pretty common?

Second, is it correct and necessary to make all changes to the global
variable inside a locked region, in both the form thread and the
background thread?

Third, I added that "catch (ObjectDisposedException)" because if the
form was closed before the background thread finished, I would get an
exception when the background thread tried to invoke the window. Does
it make sense that I would have to do this every time I use
"control.Invoke" from another thread? Is there a better way to handle
this?

Fourth, can anybody recommend a book/article with more information
about the interaction between background threads and the GUI thread,
and about .NET concurrency in general?

Thanks!

----ScottG.
 
S

Scott Gifford

As of CF 2.0 you *can* pass arguments.

Ah, thanks! As you guessed, my last project was in CF 1.x and I
didn't realize this had changed.

So now I have this. Is this a reasonable approach?

class Test : Form {
private delegate void PropSetDelegate(string s);

private void UpdateStatus(string s)
{
lblStatus.Text = s;
}

public void ThreadUpdateStatus(string s)
{
try
{
this.Invoke(new PropSetDelegate(UpdateStatus),
new Object[] { s });
}
catch (ObjectDisposedException)
{
// Do nothing
}
}
}

I see CF 2.0 added anonymous methods, too. That allow this approach,
which seems fairly nice:

public void ThreadUpdateStatus(string s)
{
try
{
this.Invoke(new EventHandler(delegate(object sender2, EventArgs e2)
{
lblStatus.Text = s;
}));
}
catch (ObjectDisposedException)
{
// Do nothing
}
}

Thanks for any feedback!

----ScottG.
 
G

Guest

Depends on how often it's called. I typically have a module-level variable
for the delegate so I'm not creating a new one every time I want to update
the UI, but the code you have is fine.


--

Chris Tacke, Embedded MVP
OpenNETCF Consulting
Managed Code in an Embedded World
www.OpenNETCF.com


Scott Gifford said:
As of CF 2.0 you *can* pass arguments.

Ah, thanks! As you guessed, my last project was in CF 1.x and I
didn't realize this had changed.

So now I have this. Is this a reasonable approach?

class Test : Form {
private delegate void PropSetDelegate(string s);

private void UpdateStatus(string s)
{
lblStatus.Text = s;
}

public void ThreadUpdateStatus(string s)
{
try
{
this.Invoke(new PropSetDelegate(UpdateStatus),
new Object[] { s });
}
catch (ObjectDisposedException)
{
// Do nothing
}
}
}

I see CF 2.0 added anonymous methods, too. That allow this approach,
which seems fairly nice:

public void ThreadUpdateStatus(string s)
{
try
{
this.Invoke(new EventHandler(delegate(object sender2,
EventArgs e2)
{
lblStatus.Text = s;
}));
}
catch (ObjectDisposedException)
{
// Do nothing
}
}

Thanks for any feedback!

----ScottG.
 

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