Home All Groups Group Topic Archive Search About

Multithreading problem in Windows Form app

Author
19 Jan 2006 6:22 PM
Juan Dent
Hi,

I have a tough problem in a Windows Form app. It uses the background worker
object to do some, well, background work. I need this because I want this
worker to be feeding a listbox logging its progress. I am using the correct
protocol to deal with interthread call from the worker to the listbox, ie.:

--------
private void AddLineOfInfo( string info )
{
    this.txtProgress.Text += info;
}
private delegate void ClearInfo();
private void AddThisInfo( string info )
{
           Invoke( new SetInfo( this.AddLineOfInfo), new object[] { info } );
}
-----------------

So I only directly call AddThisInfo. This seems to work fine. However, I
need to access this method from an object created in the background worker
thread. So I thought I would pass 'this' as a parameter to this new object's
constructor. 'this' is a form...and I think the problem starts here!

When I invokee the constructor of this new object passing 'this', the
debugger becomes sort of frozen for a bit and then finally when it allows me
to Break All, the worker thread seems blocked -- no action whatsoever.

All in all, the app freezes and I am forced to Stop Debugging.


My theory is that one thread is having difficulty accessing the form on the
other thread. The exact explanation is what I lack!!

Any insight?

--
Thanks in advance,

Juan Dent, M.Sc.

Author
20 Jan 2006 5:39 AM
Peter Huang" [MSFT]
Hi Juan,

From you description, I understand that you want to implement
multithreading in Windows Forms.
If I misunderstood, please feel free to let me know.

Almost all the UI controls are not thread safe, including the Form class.

From the MSDN, we know that a non-static form object is not thread safe. We
can not access an object which is not thread safe from other threads other
than the thread that creates the object. This may cause unexpected behavior.

"Thread Safety
Any public static (Shared in Visual Basic) members of this type are thread
safe. Any instance members are not guaranteed to be thread safe."

Here are some links about how to implement multithreading in Windows Forms.
Safe, Simple Multithreading in Windows Forms, Part 1
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnforms/htm
l/winforms06112002.asp

Safe, Simple Multithreading in Windows Forms, Part 2
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnforms/htm
l/winforms08162002.asp

Safe, Simple Multithreading in Windows Forms, Part 3
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnforms/htm
l/winforms01232003.asp

If you still have any concern, please feel free to let me know.
I look forward to hearing from you.

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
Author
22 Jan 2006 6:00 PM
Peter Ritchie
As Peter Huang pointed out access to windows controls (including their
properties) is not thread safe.  This is rooted from deep within Windows,
it's not something new to .NET development.  The gist of content of his
references is that you must force the thread that created the control to
perform the operation.  This is done via a delegate and a call to Invoke or
BeginInvoke.  This can be generalized further by testing InvokeRequired.

In your example you could make your AddLineOfInfo method thread safe as
follows:
private delegate void AddLineOfInfoDelegate(string info);
private void AddLineOfInfo(string info)
{
    if(InvokeRequired)
    {
        Invoke(new AddLineOfInfoDelegate(AddLineOfInfo), new object[] {info});
    }
    else
    {
        txtProgress.Text += info;
    }
}

With other methods, depending on the method, you may not need to declare
your own delegate.  For example, if you had a method with a object and an
EventArgs
private void MyMethod(object sender, EventArgs e)
{
    if(InvokeRequired)
    {
        Invoke(new EventHandler(MyMethod), new object[] {sender, e});
    }
    else
    {
        txtProgress.Text += info;
    }
}

Many of the Forms multit-hreading examples show assigning the new delegate
to a variable before invocation (from .NET Framework Developer's Guide -
Multithreaded Windows Forms Control Sample):
private EventHandler onSearchComplete;
//...
onSearchComplete = new EventHandler(OnSearchComplete);
//...
BeginInvoke(onSearchComplete, new object[] {this, EventArgs.Empty});

With low-frenquency methods I prefer not to pollute the class with variables
when they don't really add value.

In Visual Studio 2005 (.NET 2.0) you will actually get exceptions with some
of the debugging helpers when you perform thread unsafe access to forms and
their properties, which is a little more helpful then a hang or a crash.

Show quote
"Juan Dent" wrote:

> Hi,
>
> I have a tough problem in a Windows Form app. It uses the background worker
> object to do some, well, background work. I need this because I want this
> worker to be feeding a listbox logging its progress. I am using the correct
> protocol to deal with interthread call from the worker to the listbox, ie.:
>
> --------
> private void AddLineOfInfo( string info )
> {
>     this.txtProgress.Text += info;
> }
> private delegate void ClearInfo();
> private void AddThisInfo( string info )
> {
>            Invoke( new SetInfo( this.AddLineOfInfo), new object[] { info } );
> }
> -----------------
>
> So I only directly call AddThisInfo. This seems to work fine. However, I
> need to access this method from an object created in the background worker
> thread. So I thought I would pass 'this' as a parameter to this new object's
> constructor. 'this' is a form...and I think the problem starts here!
>
> When I invokee the constructor of this new object passing 'this', the
> debugger becomes sort of frozen for a bit and then finally when it allows me
> to Break All, the worker thread seems blocked -- no action whatsoever.
>
> All in all, the app freezes and I am forced to Stop Debugging.
>
>
> My theory is that one thread is having difficulty accessing the form on the
> other thread. The exact explanation is what I lack!!

AddThis Social Bookmark Button