Thread isAlive之后的事件

时间:2011-11-16 11:16:37

标签: c# winforms multithreading c#-4.0

我有一个带有标签的表格,文字为“正在载入”。

label1.Text = "Loading...";

在Form.Load中,我有一个正在做某事的新线程,让我们这样说。

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

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

   }
}

我希望在完成Thread“t”后将label1.Text属性更改为“已完成”。但在哪里以及如何改变我不知道。我正在学习Threads。我是否还需要再创建一个线程来连续检查Thread“t”的isAlive属性?

8 个答案:

答案 0 :(得分:3)

如果您的任务确实是在另一个线程中执行某些操作并将结果发布到gui中,那么您应该查看BackgroundWorker类。

如果您无法做到这一点,可以查看threading article of Joe。它应该真正回答你关于线程的所有问题。

如果您需要后台工作人员的进一步帮助,只需在网上搜索或在此搜索。 Here is one of my answers,展示了如何使用后台工作程序。

答案 1 :(得分:2)

您有多种解决方案。如果你真的想使用Thread类,你可以调用Join方法,但这会阻止UI线程,这不是一件好事。您也可以在“for”循环之后立即调用表单的Invoke方法

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

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

调用方法是必需的,因为你是在windows窗体中,而invoke方法将在UI线程上执行你的代码。

您可以查看Delegate.BeginInvoke和System.Threading.Tasks,而不是使用Thread类。它们更有效率,因为它汇集了线程并提供回调以分离您的拆解代码。

答案 2 :(得分:1)

不,一点也不。您需要向UI线程(处理表单的线程)发送消息。阅读本文以获取一些信息:How to update the GUI from another thread in C#?

答案 3 :(得分:1)

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

   }

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

                                         }));
}

或者你提出了一个事件,但在这么简单的情况下,这样做并不是那么重要

答案 4 :(得分:1)

查看.NET4附带的TPL Task Parallel Library。这使您有机会轻松启动后台工作程序并定义在第一个完成后启动的另一个任务。真正聪明的是,第二个任务(与任何其他任务一样)可以配置为在UI线程上运行,这样您就不必在任务操作中进行切换。

就像这里的小样本一样:

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

task.Start();

答案 5 :(得分:1)

如果您愿意使用Async CTP提出的asyncawait关键字,那么这是一个邪恶的酷解决方案。

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;
}

答案 6 :(得分:0)

可能最简单的事情就是让run在事件完成时引发事件,并让表单为此事件附加处理程序。

答案 7 :(得分:0)

将对标签或表单的引用传递给您的主题并使用Invokelabel1.Text="Completed"