如何使用Task.Wait避免WinForm冻结

时间:2017-03-14 18:06:04

标签: c# multithreading winforms task

所以我有类似的代码

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

无效
  

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

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

3 个答案:

答案 0 :(得分:7)

你会想要这个:

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

答案 1 :(得分:0)

首先,你必须开始任务才能等待它;)
如果要使用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

答案 2 :(得分:0)

尝试执行此操作,它对我有用:

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;
相关问题