Multithreading problem in Windows Form app

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

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?
 
Hi Graham,

From you description, I understand that after a team member hides a task on
his timesheet, it is no longer displayed on the views called 'View Resource
Assignments' and 'Adjust Actuals'. You want to know if this is by design.

If I misunderstood, please feel free to let me know.

Based on my research, this is by design. After you hide a task in a
timesheet, the task cannot be displayed again unless the project manager
republishes or updates it. When tasks are republished or updated, they
appear again in your timesheet automatically.

If you do not want to view all the tasks in the Timesheet View, we can use
the Filter option to show the tasks we want by clicking the link "Filter,
Group, Search" on the "View my tasks" page. We can also define a custom
filter to show the tasks more flexibly.

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

When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
=====================================================
Business-Critical Phone Support (BCPS) provides you with technical phone
support at no charge during critical LAN outages or "business down"
situations. This benefit is available 24 hours a day, 7 days a week to all
Microsoft technology partners in the United States and Canada.


This and other support options are available here:
BCPS:
https://partner.microsoft.com/US/technicalsupport/supportoverview/40010469
Others: https://partner.microsoft.com/US/technicalsupport/supportoverview/

If you are outside the United States, please visit our International
Support page: http://support.microsoft.com/common/international.aspx.
=====================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
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.
 
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.

--
http://www.peterRitchie.com/


Juan Dent said:
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!!
 
Back
Top