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..@fabricioControl.invoke
/Control.BeginInvoke
在正确使用async
/wait
时是不必要的。你能使用async wait吗?也永远不要调用新任务(foo)
,冷任务很容易出错(就像你做的那样)。使用Task.Run(
或Task.Factory.StartNew
代替。阅读关于begin invoke..@fabricioControl.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);
完全合法。