Asynchronous threads returning a result

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Cainnech
    New Member
    • Nov 2007
    • 132

    Asynchronous threads returning a result

    Hello everybody,

    I'm currently trying to get into multithreading to take care of my recurring tasks.

    In some cases I need to perform tasks recurring for the entire duration of which the application is running.

    One simple example is to display the current time.

    I could just use a simple timer but that's probably not best practice. So I understand that I need to use a separate thread to do this. And since I need this clock to be pretty accurate I probably should assign a single thread to this one process in stead of using the thread pool and I would need to use it asynchronously so that the UI is not waiting for the separate thread to finish.

    So I'm thinking of creating a process where I get the time from the pc and I extract the hours, minutes and seconds from it. Then I put in a thread.sleep for 100 ms and execute it again. In order for me to control the execution I'm also thinking of putting in a start and a stop-method.
    Starting would be pretty straightforward , when you invoke the thread, that's your start but the problem is how to stop it?

    I know I probably should be using the BeginInvoke, EndInvoke and IAsyncResult to achieve all this but I'm not sure how to get the pieces working together.

    Code:
    while(clockActivated)
    {
      string currentTime;
      currentTime = DateTime.Now.ToString("HH:mm:ss tt");
      lblClock.Text = currentTime;
      Thread.Sleep(10);
    }
    So basically my questions are:
    - How can I start a thread which runs continuously?
    - How can I pass the result back to a label on my form?
    - How can I stop the thread which is in a continuous loop?

    I hope some here can help me.
    Thanks,
    Kenneth
  • Joseph Martell
    Recognized Expert New Member
    • Jan 2010
    • 198

    #2
    You have several options, but which one is best is really going to depend on exactly what you are trying to accomplish, how precise your timing needs to be, and what version of .Net you are using. New parallel processing classes were introduced with 4.0, I believe.

    I would probably use System.Timers.T imer for this task (this is NOT System.Windows. Forms.Timer). It has several advantages. The timing is very accurate, so you shouldn't have any problems with missed updates. Also, the interface is pretty straight-forward and easy to use. Finally, you can cause it to execute code on the same thread as the UI, so updating UI elements becomes much easier.

    The thing to remember is that just because you have started a thread doesn't mean you have to relinquish control of that thread in other areas of your code. In the following example, the form load event defines and starts the updater thread. Notice that the variable is actually defined at the class level, not inside the form load event. This makes it accessible everywhere in the form. The thread is stopped when someone clicks the stop button. The timer event handler does all of the updating and because the SynchronizingOb ject was set to the form itself the event handler is executing on the UI thread:

    Code:
            private System.Timers.Timer _updater = null;
            private void frmTest_Load(object sender, EventArgs e)
            {
                _updater = new System.Timers.Timer(100);
                _updater.SynchronizingObject = this;
                _updater.AutoReset = true;
                _updater.Elapsed += new System.Timers.ElapsedEventHandler(_updater_Elapsed);
                _updater.Start();
            }
    
            void _updater_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
            {
                lblClock.Text = DateTime.Now.ToString("HH:mm:ss tt");
            }
    
            private void btnStopTimer_Click(object sender, EventArgs e)
            {
                _updater.Stop();
            }
    Check out this post for some interesting information on the different timers available (an older article, but still good):

    Comment

    • Cainnech
      New Member
      • Nov 2007
      • 132

      #3
      Hello Joseph,

      Thanks for yor reply and the sample code.
      I was aware that Timer class executes the timer itself on another thread, but in the example you gave, the _updater_Elapse d is still executed on the UI-thread and not on the timer thread, is that correct?

      Because in this case it's a simple clock I want to display but there's a case where I need to poll a webservice every two seconds, which returns data in an XML or JSON format, which I need to process. I can't have it do that on my UI-thread or it will make my UI unresponsive.

      Comment

      • Joseph Martell
        Recognized Expert New Member
        • Jan 2010
        • 198

        #4
        You are correct, but the reason it executes on the UI thread is specifically because of line 5 in my example code:
        Code:
        _updater.SynchronizingObject = this;
        Using a synchronizing object like the windows form ('this' points to the containing form) causes the Elapsed event handler to be executed on the same thread as the UI. Leaving the Synchronizing Object set to null means that the event handler will execute on a separate thread. That is one of the places where the differences between System.Windows. Forms.Timer and System.Timers.T imer really shows up.

        Two other points, since you mentioned web services:
        1. You should be able to use asynchronous calls to the web service if you are using WCF. Just add an event handler for when the call returns and then you don't have to really worry about holding up your UI thread because you blocked an a web service call. (Click on "Advanced" when adding the service reference and there should be a check box for "Generate asynchronus operations" in VS 2008)
        2. If you want to handle the multithreaded call to a web service yourself, you should disable the recurring execution of the web service thread at the start of your event handler (and re-enable it just before the end). If the web service takes a long time to respond for some reason you could have a pile up of Elapsed event handlers executing at the same time. That would be a lot of processing for not much reward.

        Comment

        Working...