4 Replies - 1197 Views - Last Post: 06 August 2012 - 06:00 AM Rate Topic: -----

#1 lbytesxk  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 13
  • Joined: 05-May 09

GUI runs a task on a background thread still unresponsive

Posted 03 August 2012 - 01:15 PM

I have a piece of code in a form, I want the form to remain responsive and update some status strip items, one is a clock that shows system time including the seconds, and the other informs the user what task is being underway and includes a GIF image that is a 2 circular arrows rotating.
Here is the code, I'm only including the 2 functions, one is creating a thread and starts it, the other just does some task and updates the status strips
private void _doSomething()
        {            
            try
            {
                _thread = new Thread(DoSomething);
                _thread.Start();
                while (_thread.ThreadState == System.Threading.ThreadState.Running)
                {
                    Application.DoEvents();
                    this.Refresh();
                    Thread.Sleep(50);
                }
                _thread.Join();
                
            }
            catch (Exception ex)
            { MessageBox.Show (ex.ToString()); }
            finally
            {                 
                _thread = null;               
            }
        }


private void DoSomething()
        {
            string _result = string.Empty;
            this.toolStripStatusLabel5.Text = "doing something.....";
            this.toolStripStatusLabel5.Image = workingImg;
            
            Something.Utilities _utilities = new Something.Utilities();
            _result = _utilities.DoStuff(_pfsui, _pfspw, _pfsSocket, _pfsHost, _pfsSendPort, _sn, _an);
            
            if (_result.Contains("OK"))
            {

                _utilities = null;                             
                
            }
            else
            {  _utilities = null;  }
            this.toolStripStatusLabel5.Text = string.Empty;
            this.toolStripStatusLabel5.Image = null;            
        }



Now, while the GUI is up and idle the seconds in the time display in the status strip are ticking. However when the _doSomething function being called the time display freezes for the duration of the function and also the "workingImg" which is the gif is not being animated.
I don't know what I'm doing wrong here. This is such a simple app that I don't want to redo it with the BackGroundWorker class.
thanks

Is This A Good Question/Topic? 0
  • +

Replies To: GUI runs a task on a background thread still unresponsive

#2 CodingSup3rnatur@l-360  Icon User is online

  • D.I.C Addict
  • member icon

Reputation: 916
  • View blog
  • Posts: 921
  • Joined: 30-September 10

Re: GUI runs a task on a background thread still unresponsive

Posted 03 August 2012 - 02:14 PM

You're starting your thread, which is fine, but then you are looping for some reason? You don't need the while loop. The Thread.Sleep() will just be tying up the UI thread, meaning the UI becomes unresponsive. What was your thinking behind that loop, just out of interest, as it seems to show a fundamental misunderstanding of how threads work :)

Further, you are calling Thread.Join(), which will block the UI thread until your thread has terminated, thus guaranteeing the UI won't be responsive until your thread terminates.

In the current set up of your code, you are pretty much gaining nothing from the thread you create.

Also, you should not be updating UI controls from any thread other than the UI thread. Have a read of this.

This:

 
 string _result = string.Empty;
 Something.Utilities _utilities = new Something.Utilities();
 _result = _utilities.DoStuff(_pfsui, _pfspw, _pfsSocket, _pfsHost, _pfsSendPort, _sn, _an);


and possibly:

if (_result.Contains("OK"))
{
    _utilities = null;                                      
}
else
{  
    _utilities = null;  
}



is the only bit of code that should be in running in your thread.

You also need to remove the finally block in the _doSomething() method when you remove the while loop, and the call to Thread.Join().

I'd also question whether _thread should really be an instance variable, or whether it should be local to the _doSomething method.


This is what you need to do:

Add these two lines just before you start your thread:

this.toolStripStatusLabel5.Text = "doing something.....";
this.toolStripStatusLabel5.Image = workingImg;



Then start the thread which runs DoStuff().

Once you have the result from the DoStuff() method, do what you need to do with it, and make sure you use the technique in the above linked article to update any UI controls.


If you don't want to use a BackgroundWorker, you'd probably be better off creating a wrapper class around the Something.Utilities(); that can handle all the threading details, and then raise an event when the result is available that the form class can subscribe to to get the result. This will free the form class of all this threading responsibility.

However, don't worry about that. Just try and get it working the way you have it at the moment. Here is a tutorial regarding what I was just talking about though that might be a good idea to look at :)

This post has been edited by CodingSup3rnatur@l-360: 03 August 2012 - 02:54 PM
Reason for edit:: Removed reference to 'background' thread as not technically accurate

Was This Post Helpful? 1
  • +
  • -

#3 Curtis Rutland  Icon User is online

  • (╯°□°)╯︵ (~ .o.)~
  • member icon


Reputation: 3803
  • View blog
  • Posts: 6,409
  • Joined: 08-June 10

Re: GUI runs a task on a background thread still unresponsive

Posted 03 August 2012 - 02:24 PM

Lines 9, 10, and 11 are keeping your UI thread completely busy (or sleeping). Since you're using or sleeping your GUI thread non-stop, the GUI can't be responsive.

Basically, what you've done is move your work to the other thread, and then made your main thread wait in an unusable state until the other thread is done.

Try something: comment out lines 3, 4, and then 7 through 21. The only thing your method should have is:

                _thread = new Thread(DoSomething);
                _thread.Start();


If you really want to null out your thread, move that to the end of DoSomething.

Otherwise, I really do suggest using a background worker or a task. They were designed to simplify this kind of thing; to make it easier on you.

Edit: The above poster is very very knowledgeable about threading. I'm going to re-link his tutorial just to make sure you got it:

http://www.dreaminco...ui-environment/
Was This Post Helpful? 1
  • +
  • -

#4 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 1934
  • View blog
  • Posts: 5,759
  • Joined: 05-May 12

Re: GUI runs a task on a background thread still unresponsive

Posted 03 August 2012 - 02:32 PM

And no matter what VB programmers tell you, DO NOT USE Application.DoEvents() unless you know exactly what you are doing.

When you call Application.DoEvents(), it starts processing messages in the message queue until the queue is empty again. In the process of handling messages, your code can (and will) be reentered. Unless you write code anticipating the possibility of reentry, you will be in for at least several hours worth, if not days worth (my record was 7 days), of strange hard to reproduce, and even harder to explain bugs. I had a very long conversation with the guy who stuck in the Application.DoEvents() line because "that's what it said on the Internet if your program isn't painting fast enough." *sigh*
Was This Post Helpful? 1
  • +
  • -

#5 lbytesxk  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 13
  • Joined: 05-May 09

Re: GUI runs a task on a background thread still unresponsive

Posted 06 August 2012 - 06:00 AM

Thanks a lot for everyone who took their time and replied. I did learn a couple of things that is very helpful. I almost exclusively use BackgroundWorker class for multi threading and the added loop was someone showed me how to put a task on a thread separate from the GUI so that's where that comes from. I guess I should pay really close attention what people tell me :)
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1