Click to See Complete Forum and Search --> : Serious GUI threading problem.


jhammer
September 26th, 2006, 11:00 AM
I have a weird problem.

I have a form with a button. When the user press on the button I want to perform a long task. While the task is executed the GUI is disabled, yet it should be alive (no "Not Responding" in the title). When the long task is finished I need to enable the GUI.

Here is the code:

public MyForm:Form
{
(...)

private delegate void VoidDelegate();

private void btn_Click(object sender, EventArgs e)
{
DisableGUI();
VoidDelegate dlg = new VoidDelegate(PerformLongTask);
dlg.BeginInvoke(new AsyncCallback(TaskEnded),null);
}

private void TaskEnded(IAsyncResult ar)
{
EnableGUI(); //Set the Enabled of all the controls to true
}
}



The TaskEnded method throws an exception, because I cannot access the GUI from a different thread. So I figured this solution:

private void TaskEnded(IAsyncResult ar)
{
if (this.InvokeRequired)
{
this.Invoke(new AsyncCallback(TaskEnded), new object() { ar } );
return;
}
EnableGUI(); //Set the Enabled of all the controls to true
}


So if I am from a different thread, I execute the method from the GUI thread using Invoke.
This works most of the times, but in some rare occasions, the Invoke method simply get stuck. Any ideas what the problem is?

torrud
September 26th, 2006, 11:52 AM
I do not see any problem. Maybe you want to have a look at two articles I found about background processing in Windows Forms Applications.

The first article is useful if you use .NET 1.1 and the second for .NET 2.0.

part 1 (http://www.microsoft.com/belux/msdn/nl/community/columns/himschoot/backgroundprocessing.mspx)

part 2 (http://www.microsoft.com/belux/msdn/nl/community/columns/himschoot/backgroundprocessing2.mspx)

Maybe you find your answer there.

jhammer
September 26th, 2006, 12:16 PM
The first article was really nice, but unfortunately it is similar to my code. Still my code get stuck.

jhammer
September 27th, 2006, 04:52 AM
I was given a hint that the GUI thread is busy, so the Invoke call is blocked. How can I know if the GUI thread is busy from another thread? Maybe there is a different problm that I am not seeing?

laasunde
September 27th, 2006, 05:34 AM
Could one thread be blocking the other (deadlock) ?

I believe Invoke() is a blocking call, could you possibly use BeginInvoke() instead for the GUI-Enable call ? (Just a guess).

Could you post your current code.

Btw, this site (http://www.albahari.com/threading/index.html) has a lot of good information about threads.

jhammer
September 27th, 2006, 07:01 AM
BeginInvoke did not solve the proble, the GUI still gets stuck.
Is there a way to find out if the GUI thread is busy and cannot be accessed at that instance?

zips
September 27th, 2006, 10:51 AM
I use something like this successfully:
WaitHandle[] AWait = new WaitHandle[] { new AutoResetEvent(false) };

DisableGUI();

Thread AThread = new Thread(new ThreadStart(PerformLongTask));

AThread.Start();

while (AThread.IsAlive)
{
WaitHandle.WaitAny(AWait, 50, false);
Application.DoEvents();
}

EnableGUI();
The DoEvents keeps the GUI alive and well.