[英]C# Invoking causes Task never complete
这是我的代码:
public void ReadCodes(){
Task compute = Task.Run(() =>
{
//foo code
foreach (var line in lines)
{
//some other codes
SetText("doing something");
}
});
compute.Wait();
//some other foo
}
private void SetText(string text)
{
if (this.lblUsedFiles.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.lblUsedFiles.Text = text;
}
}
当我删除SetText("doing something")
调用ReadCodes()
函数,否则它会挂起。 我的代码出了什么问题? 我想在Task.Run()
更新UI。
您的ReadCodes
方法(可能在UI线程上执行)产生一个新任务,并阻塞等待它 - UI线程在完成之前不能执行任何其他操作。
但是,您的任务(在线程池上运行)调用Invoke
在UI线程上运行操作,也阻塞直到完成。 由于两个操作都被阻塞等待,因此两者都无法继续,从而导致死锁。
要解决此问题,最简单的解决方案通常是使用BeginInvoke
替换您的Invoke
,从而允许您的任务继续(并完成),而无需等待UI更新。 任务完成后,将释放UI线程,并处理挂起的UI更新。
编辑 :响应更新的问题以包含循环:我建议您使用异步模式(在C#5中引入)。 这将完全消除UI线程阻塞,并允许您在处理每一行时立即执行UI更新。
public async Task ReadCodes()
{
foreach (var line in lines)
{
string text = await Task.Run(() =>
{
//foo code
// return text;
});
this.lblUsedFiles.Text = text;
}
//some other foo
}
编辑2 :我根据Peter Duniho的评论更新了我的代码。 由于ReadCodes
可能是在UI线程上调用的,因此您可以在等待每个任务时直接在其中更新UI(无需Invoke
)。 我假设在//some other codes
执行的后台处理可以集成到后续迭代的//foo code
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.