Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用任务避免WinForm冻结。请稍候_C#_Multithreading_Winforms_Task - Fatal编程技术网

C# 如何使用任务避免WinForm冻结。请稍候

C# 如何使用任务避免WinForm冻结。请稍候,c#,multithreading,winforms,task,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()

所以我有类似的代码

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;});
但是抛出一个
invalidoOperationException
是不起作用的:

调用线程无法访问此对象,因为另一个 线程拥有它

我怎样才能解决这个问题?也许我应该使用完全不同的方法来实现我想要的。谢谢。

您会想要这个:

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();
}
你会想要这个:

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

首先,您必须启动任务,以便能够等待它;)
如果要使用ContinueWith()而不是async/wait,只需使用选项
TaskContinuationOptions.ExecuteSynchronously
。这将导致在调用线程中执行延续操作。


首先,您必须启动任务,以便能够等待它;)
如果要使用ContinueWith()而不是async/wait,只需使用选项
TaskContinuationOptions.ExecuteSynchronously
。这将导致在调用线程中执行延续操作。


试着这样做,它对我有用:

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;

试着这样做,它对我有用:

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;

你能使用异步等待吗?另外,永远不要调用
新任务(foo)
,冷任务很容易出错(就像你做的那样)。使用
Task.Run(
Task.Factory.StartNew
代替。阅读关于begin invoke..@fabricio
Control.invoke
/
Control.BeginInvoke
在正确使用
async
/
wait
时是不必要的。你能使用async wait吗?也永远不要调用
新任务(foo)
,冷任务很容易出错(就像你做的那样)。使用
Task.Run(
Task.Factory.StartNew
代替。阅读关于begin invoke..@fabricio
Control.invoke
/
Control.BeginInvoke
在正确使用
async
/
wait
时是不必要的。谢谢。但我想应该是这样的
wait Task.Run(()=>DoSomething())
。如果我是对的,请编辑。@denisloik不,
DoSomething
有一个有效的
Func
签名,这是
Run
的重载之一,所以执行
Task.Run(DoSomething);
是完全合法的。谢谢。但我想应该是这样的
wait Task.Run(()=>DoSomething())
。如果我是对的,请编辑。@DenisLolik否,
DoSomething
具有有效的
Func
签名,这是
Run
的重载之一,因此执行
Task.Run(DoSomething);
完全合法。