首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >等待Task.Delay()与Task.Delay().Wait()

等待Task.Delay()与Task.Delay().Wait()
EN

Stack Overflow用户
提问于 2014-11-07 18:13:00
回答 1查看 117.2K关注 0票数 71

在C#中,我有以下两个简单的示例:

代码语言:javascript
复制
[Test]
public void TestWait()
{
    var t = Task.Factory.StartNew(() =>
    {
        Console.WriteLine("Start");
        Task.Delay(5000).Wait();
        Console.WriteLine("Done");
    });
    t.Wait();
    Console.WriteLine("All done");
}

[Test]
public void TestAwait()
{
    var t = Task.Factory.StartNew(async () =>
    {
        Console.WriteLine("Start");
        await Task.Delay(5000);
        Console.WriteLine("Done");
    });
    t.Wait();
    Console.WriteLine("All done");
}

第一个示例创建了一个打印"Start“的任务,等待5秒打印"Done”,然后结束任务。我等待任务完成,然后打印"All done“。当我运行测试时,它会按预期运行。

第二个测试应该具有相同的行为,除了任务内部的等待应该是非阻塞的,因为使用了async和await。但这个测试只是打印"Start“,然后立即打印"All done”和"Done“。

我不知道为什么我会有这样的行为:I‘如果有任何帮助,我将非常感激:)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-11-07 18:34:50

第二个测试有两个嵌套的任务,您正在等待最外层的任务,要解决这个问题,您必须使用t.Result.Wait()t.Result获得内部任务。

第二种方法大致相当于此:

代码语言:javascript
复制
public void TestAwait()
{
  var t = Task.Factory.StartNew(() =>
            {
                Console.WriteLine("Start");
                return Task.Factory.StartNew(() =>
                {
                    Task.Delay(5000).Wait(); Console.WriteLine("Done");
                });
            });
            t.Wait();
            Console.WriteLine("All done");
}

通过调用t.Wait(),您正在等待立即返回的最外层的任务。

处理这种情况的最终“正确”方法是完全放弃使用Wait,只使用await。将UI附加到异步代码后,Wait可能会导致deadlock issues

代码语言:javascript
复制
    [Test]
    public async Task TestCorrect() //note the return type of Task. This is required to get the async test 'waitable' by the framework
    {
        await Task.Factory.StartNew(async () =>
        {
            Console.WriteLine("Start");
            await Task.Delay(5000);
            Console.WriteLine("Done");
        }).Unwrap(); //Note the call to Unwrap. This automatically attempts to find the most Inner `Task` in the return type.
        Console.WriteLine("All done");
    }

更好的做法是使用Task.Run来启动异步操作:

代码语言:javascript
复制
    [TestMethod]
    public async Task TestCorrect()
    {
        await Task.Run(async () => //Task.Run automatically unwraps nested Task types!
        {
            Console.WriteLine("Start");
            await Task.Delay(5000);
            Console.WriteLine("Done");
        });
        Console.WriteLine("All done");
    }
票数 75
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26798845

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档