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



所以我有类似的代码

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不起作用:

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

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

您需要此:

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

首先,您必须启动任务才能等待它;)
如果要使用continewith()而不是异步/等待,则可以使用选项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

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

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;

最新更新