【问题标题】:How to avoid UI hanging with Invoke?如何避免使用 Invoke 挂起 UI?
【发布时间】:2012-10-25 05:36:19
【问题描述】:

以下代码使 UI 线程挂起。

    private void button1_Click(object sender, EventArgs e)
    {
        Thread t = new Thread(Func);
        t.Start();
    }

    private void Func()
    {
        this.Invoke((Action)(() =>
        {
            while (true);
        }));
    }

我希望在不同的工作线程中调用 Func(),而不会在每次单击按钮时冻结任何 UI 线程。

最好的解决方法是什么?

【问题讨论】:

  • 为什么你把while (true);放在Invoke方法中,你没有任何代码改变UI,它会阻塞UI线程,
  • 我想在循环中添加一些代码更改 UI。我只是在循环中省略了这些代码以使其看起来简单。谢谢。

标签: c# multithreading invoke


【解决方案1】:

使用您的代码,while(true) 在 UI 线程上运行,这就是阻止您的 UI 的原因。

while(true)放到Invoke方法外面,所以当你想改变UI的时候,把改变UI的代码块放在Invoke里面:

private void button1_Click(object sender, EventArgs e)
{
    Thread t = new Thread(Func);
    t.Start();
}

private void Func()
{
    while(true)
    {
       this.Invoke((Action)(() =>
        {
            textBox.Text = "abc";
        }));
    } 
}

【讨论】:

  • 谢谢。这对我有很大帮助。有什么办法可以同时接受这两个答案吗?
【解决方案2】:

Func() 代码确实在非 UI 线程上运行。但是,this.Invoke 然后在 UI 线程上执行 Action!。

试试这样的:

void Func()
{
     // Do some work.

     // Update the UI (must be on UI thread)
     this.Invoke(Action) (() =>
     {
        // Update the UI.
     }));
 }

我可能会更好地使用BeginInvoke 方法。这样,非 UI 线程就不会等待 UI 线程执行 Action。

此外,您没有异常捕获或进度报告逻辑。我建议查看BackgroundWorker 类; http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx.

void button1_Click(object sender, EventArgs e)
{
   var worker = new BackgroundWorker();
   worker.DoWork += (s,e) =>
   {
       // Do some work.
   };
   worker.RunWorkerCompleted += (s,e) =>
   {
       // Update the UI.
   }
   worker.RunWorkerAsync();
}

【讨论】:

  • 我很感激。非常感谢。
猜你喜欢
  • 2021-08-03
  • 2013-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多