【问题标题】:How to avoid WinForm freezing using Task.Wait如何使用 Task.Wait 避免 WinForm 冻结
【发布时间】:2017-03-14 18:06:04
【问题描述】:

所以我有类似的代码

private void doSmth()
{
   str = makeStr();
}
private void button_Click(object sender, EventArgs e)
{
   Task task = new Task(doSmth);
   task.Start();
   task.Wait();
   textBox.Text = str;
}

太冷了,我知道为什么会因为Wait() 而发生这种情况。我试图像这样使用ContinueWith()

task.ContinueWith((t) => {textBox.Text = str;});

但抛出InvalidOperationException 不起作用:

调用线程无法访问该对象,因为不同的 线程拥有它

我该如何解决这个问题?也许我应该完全使用另一种方法来实现我想要的。谢谢。

【问题讨论】:

  • 可以使用异步等待吗?也永远不要打电话给new Task(foo),冷任务很容易搞砸(就像你做的那样)。请改用Task.Run(Task.Factory.StartNew
  • 阅读开始调用..
  • @fabricio Control.Invoke/Control.BeginInvoke 在您正确使用async/await 时是不必要的。

标签: c# multithreading winforms task


【解决方案1】:

你会想要这个:

private String DoSomething() {

    return makeStr(); // return it, don't set it to a field.
}

private async void button_Click(...) {

    String result = await Task.Run( DoSomething );
    textBox.Text = result;
}

...相当于这个:

private async void button_Click(...) {

    // Task<> is the .NET term for the computer-science concept of a "promise": https://en.wikipedia.org/wiki/Futures_and_promises
    Task<String> resultPromise = Task.Run( DoSomething ); 
    String result = await resultPromise;
    textBox.Text = result;
}

...这(大致)相当于:

private void button_Click(...) {

    Thread thread = new Thread( () => {

        String result = DoSomething();
        this.BeginInvoke( () => {

            this.textBox.Text = result;
        } );

    } );
    thread.Start();
}

【讨论】:

  • 谢谢。但我想应该是这样的await Task.Run(() =&gt; DoSomething())。如果我是对的,请编辑。
  • @DenisLolik 不,DoSomething 有一个有效的Func&lt;string&gt; 签名,这是Run 的重载之一,所以这样做Task.Run( DoSomething ); 是完全合法的。
【解决方案2】:

首先你必须启动任务才能等待它;)
如果你想使用 ContinueWith() 而不是 async/await,你可以使用选项TaskContinuationOptions.ExecuteSynchronously。这将导致在调用线程中执行继续操作。

Task task = new Task(doSmth);
task.ContinueWith(t => textBox.Text = str, TaskContinuationOptions.ExecuteSynchronously);
task.Start();
//task.Wait(); // optional if you want to wait for the result

【讨论】:

    【解决方案3】:

    试试这个,它对我有用:

    Task ts =new Task(new Action(()=>{
    //your code here
    }
    ));
    ts.Start();//start task
    
    //here we wait until task completed
    while (!ts.IsComplete)//check until task is finished
    {
    //pervent UI freeze
    Application.DoEvents();
    }
    //Task Completed
    //Continue with ...
    textBox.Text = ts.Result;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-27
      • 1970-01-01
      • 1970-01-01
      • 2017-07-14
      • 2018-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多