C#调用原因任务永远不会完成

May*_*sam 3 c# multithreading

这是我的代码:

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;
        }
}
Run Code Online (Sandbox Code Playgroud)

当我删除SetText("doing something")呼叫ReadCodes()功能工作,否则它挂起.我的代码出了什么问题?我想在里面更新UI Task.Run().

Dou*_*las 5

您的ReadCodes方法(可能在UI线程上执行)会生成一个新任务,并阻塞等待它 - UI线程在完成之前不能执行任何其他操作.

但是,您的任务(在线程池上Invoke运行)调用在UI线程上运行操作,也阻塞直到完成.由于两个操作都被阻塞等待,因此两者都无法继续,从而导致死锁.

要解决此问题,最简单的解决方案通常是替换您InvokeBeginInvoke,允许您的任务继续(并完成)而无需等待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
}
Run Code Online (Sandbox Code Playgroud)

编辑2:我根据Peter Duniho的评论更新了我的代码.由于ReadCodes可能是在UI线程上调用,因此您可以Invoke在等待每个任务时直接在其中更新UI(无需).我假设执行的后台处理//some other codes可以集成到后续迭代中//foo code.