0

I have a Form with a Label with text "Loading".

label1.Text = "Loading...";

In Form.Load I have a new Thread which is doing something, lets say this.

void Form_Load(object sender, EventArgs args)
{
   Thread t = new Thread(run);
   t.Start();
}  

void run()
{
   for(int i = 0; i < 1000000; i++)
   {

   }
}

I want to change label1.Text property to "Finished" after the completion of Thread "t". But where and how to change I don't have any idea. I am learning Threads. Do I have to create one more thread to do this which continouously checks the isAlive property of Thread "t"?

Brian Gideon
  • 47,849
  • 13
  • 107
  • 150
Sandy
  • 11,332
  • 27
  • 76
  • 122

8 Answers8

3

If your task is really doing something in another thread and post the result into the gui you should take a look at BackgroundWorker class.

If this is not possible for you, you can take a look into the threading article of Joe. It should really answer all your questions about threading.

If you need further help with the background worker, simply make a search on the web or here on SO. Here is one of my answers, showing how you can use the background worker.

Community
  • 1
  • 1
Oliver
  • 43,366
  • 8
  • 94
  • 151
2

You have multiple solution. If you really want to use the Thread class, you can call the Join method, but this will block the UI thread which is not a good thing. You could also call the Invoke method of your form right after your "for" loop as so

void run()
{
    for (int i = 0; i < 100000000; i++)
    {
    }

    this.Invoke(new Action(() => this.label1.Text = "done"));
}

The invoke method is required because you are in a windows form and the invoke method will execute your code on the UI thread.

Instead of using the Thread class, you could also have a look at Delegate.BeginInvoke and at System.Threading.Tasks. They are both more efficient since it pool the threads and the provide callback to separate your tear-down code.

Francis
  • 3,335
  • 20
  • 46
1

No, not at all. You need to send a message to the UI thread (the one that handles your form). Read this for some info: How to update the GUI from another thread in C#?

Community
  • 1
  • 1
zmbq
  • 38,013
  • 14
  • 101
  • 171
1

easy

void run()
{
   for(int i = 0; i < 1000000; i++)
   {

   }

   Invoke(new MethodInvoker(delegate()
                                         {
                                             label1.Text = "finished";

                                         }));
}

or you raise an event but in such a simple case it is not so important to do that

masterchris_99
  • 2,683
  • 7
  • 34
  • 55
1

Take a look at TPL Task Parallel Library that comes with .NET4. This gives you the chance to easy start a background worker and define another task to be started after the first one finished. The real smart thing is, that the second task (as any other) can be configured to run on the UI thread, so that you don't have to do the switching in the tasks action.

Like that little sample here:

var task = new Task(() =>
{
    // DoSomething very long in background
}).ContinueWith(previousTask =>
    {
        // Do some action on UI thread
    },
    TaskScheduler.FromCurrentSynchronizationContext());

task.Start();
Fischermaen
  • 12,238
  • 2
  • 39
  • 56
  • will appreciate if sample is based on my problem so I get a better understanding. Any related example on net or article is also appreciable. thanks. I never heard of it. – Sandy Nov 16 '11 at 11:33
  • @rapsalands: has been added :-) – Fischermaen Nov 16 '11 at 11:35
  • i did it previous one....that was accurate to my problem but yours was good for long run knowledge. thanks. – Sandy Nov 16 '11 at 11:38
1

If you are willing to use the async and await keywords proposed by the Async CTP then this is a wicked cool solution.

public async void Form_Load(object sender, EventArgs args)
{
  label1.Text = "Loading..."
  // Do some more stuff here if necessary.
  label1.Text = await Run();
}

private Task<string> Run()
{
  var tcs = new TaskCompletionSource<string>();
  Task.Factory.StartNew(
    () =>
    {
      for (int i = 0; i < 1000000; i++)
      {
      }
      tcs.SetResult("Finished");
    });
    return tcs.Task;
}
Brian Gideon
  • 47,849
  • 13
  • 107
  • 150
0

Probably the easiest thing to do is to get run to raise an event when it's complete, and have the form attach a handler to this event.

kͩeͣmͮpͥ ͩ
  • 7,783
  • 26
  • 40
0

Pass a reference to the label or form to your thread and use Invoke to label1.Text="Completed"

ChrisBD
  • 9,104
  • 3
  • 22
  • 35