等待C#中的后台线程

Lor*_*ori 0 c# multithreading async-await

有什么区别:

public class Worker
{
    public static void Execute()
    {
        ExecuteInBackgroundThread().Wait();
    }

    private static Task ExecuteInBackgroundThread()
    {
        return Task.Run(() =>
        {
            // do some long running operation
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

public class Worker
{
    public static void Execute()
    {
        ExecuteInBackgroundThread().Wait();
    }

    private static async Task ExecuteInBackgroundThread()
    {
        await Task.Run(() =>
        {
            // do some long running operation
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

我注意到Worker.Execute()从UI线程调用我的Windows Phone应用程序的第二个版本被卡住了.

相反,使用第一个版本似乎一切正常.

ExecuteInBackgroundThread实际返回的第二个版本是否Task<T>可以等待?但如果情况并非如此,编译器是否应该提出错误说我们没有返回任何内容?

i3a*_*non 5

首先,你的应用程序卡住的真正原因是你有一个僵局.那是因为你正在使用Task.Wait哪个阻塞正在等待UI线程完成的任务的UI线程.

发生这种情况是因为只有一个UI线程,因此SynchronizationContext只有使用该特定线程.

你可以通过使用来修复你的死锁ConfigureAwait(false),它不使用SynchronizationContext:

private static async Task<T> ExecuteInBackgroundThread<T>()
{
    await Task.Run(() =>
    {
        // do some long running operation
    }).ConfigureAwait(false);
}
Run Code Online (Sandbox Code Playgroud)

除此之外,两个选项几乎相同,只要没有更多的代码在ExecuteInBackgroundThread调用之外Task.Run.第一个选项稍快,因为您直接使用Task.Run中的任务.第二个选项在顶部添加另一个冗余异步层(包括状态机等).

结论:您应该使用第一个选项.但是不要使用Wait不仅会阻塞你的线程,但在某些情况下可能会导致死锁.