Task.WaitAll没有等待任务完成 [英] Task.WaitAll not waiting for task to complete

查看:2527
本文介绍了Task.WaitAll没有等待任务完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

虽然试图找出新的(也许没有现在这么新,但新的给我,反正)任务在C#中的异步编程,我遇到了那个花了问题我有点想不通,我不知道为什么。

While trying to figure out the new (maybe not so new now, but new to me, anyway) Task asynchronous programming in C#, I ran into a problem that took me a bit to figure out, and I'm not sure why.

我有固定的问题,但我仍然不知道为什么它是开始的一个问题。我只是想在那里运行到了同样的情况我想分享一下我的情况下,任何人的经验。

I have fixed the problem, but I am still not sure why it was a problem to begin with. I just thought I'd share my experience in case anyone out there runs into the same situation.

如果任何大师想告诉我这个问题的原因,那太好等等AP preciated。我总是喜欢知道刚为什么的东西不起作用!

If any gurus would like to inform me of the cause of the problem, that'd be wonderful and much appreciated. I always like knowing just why something doesn't work!

我做了一个测试任务,如下:

I made a test task, as follows:

Random rng = new Random((int)DateTime.UtcNow.Ticks);
int delay = rng.Next(1500, 15000);
Task<Task<object>> testTask = Task.Factory.StartNew<Task<object>>(
    async (obj) =>
        {
            DateTime startTime = DateTime.Now;
            Console.WriteLine("{0} - Starting test task with delay of {1}ms.", DateTime.Now.ToString("h:mm:ss.ffff"), (int)obj);
            await Task.Delay((int)obj);
            Console.WriteLine("{0} - Test task finished after {1}ms.", DateTime.Now.ToString("h:mm:ss.ffff"), (DateTime.Now - startTime).TotalMilliseconds);
            return obj;
        },
        delay
    );
Task<Task<object>>[] tasks = new Task<Task<object>>[] { testTask };

Task.WaitAll(tasks);
Console.WriteLine("{0} - Finished waiting.", DateTime.Now.ToString("h:mm:ss.ffff"));

// make console stay open till user presses enter
Console.ReadLine();

然后我运行应用程序,看看它吐出来。下面是一些示例输出:

And then I ran the application to see what it spat out. Here is some sample output:

6:06:15.5661 - 从3053ms的延迟测试任务结果
  6:06:15.5662 - 完毕等待结果。
  6:06:18.5743 - 测试任务3063.235ms完成后

6:06:15.5661 - Starting test task with delay of 3053ms.
6:06:15.5662 - Finished waiting.
6:06:18.5743 - Test task finished after 3063.235ms.

正如你所看到的, Task.WaitAll(任务); 声明没有做太多。它继续执行之前的总计1毫秒的等待着。

As you can see, the Task.WaitAll(tasks); statement didn't do much. It waited a grand total of 1 millisecond before continuing execution.

我已经回答了我自己的问题的 - 但正如我上面所说的 - 如果任何人更了解比我会照顾解释为什么这不工作,请不要!
(我的认为的一旦它到达一个的await 运营商可能有事情做与执行方法走出出' - 再退一步在曾经的等待后...但我可能是错的)

I have answered my own "question" below - but as I said above - if anyone more knowledgeable than I would care to explain why this doesn't work, please do! (I think it might have something to do with the execution 'stepping-out' of the method once it reaches an await operator - then stepping back in once the awaiting is done... But I am probably wrong)

推荐答案

您应该避免使用 Task.Factory.StartNew 与异步的await。您应该使用 Task.Run 代替。

You should avoid using Task.Factory.StartNew with async-await. You should use Task.Run instead.

这是异步方法返回一个任务&LT; T&GT; ,异步委托确实也是如此。 Task.Factory.StartNew 还返回任务&LT; T&GT; ,其中,其结果是委托参数的结果。因此一起使用时,它返回一个任务&LT;任务&LT; T&GT;&GT;方式&gt;

An async method returns a Task<T>, an async delegate does as well. Task.Factory.StartNew also returns a Task<T>, where its result is the result of the delegate parameter. So when used together it returns a Task<Task<T>>>.

所有这任务&LT;任务&LT; T&GT;&GT; 做的是执行代表,直到有返回任务,达到第一的await时,这是。如果你只是等待任务完成,你是不是第一次的await之前等待整个方法,只是一部分。

All that this Task<Task<T>> does is execute the delegate until there's a task to return, which is when the first await is reached. If you only wait for that task to complete you aren't waiting for the whole method, just the part before the first await.

您可以修复使用 Task.Unwrap 这将创建一个任务&LT; T&GT; 的再presents的任务&LT;任务&LT; T&GT;&GT;&GT;

You can fix that by using Task.Unwrap which creates a Task<T> that represents that Task<Task<T>>>:

Task<Task> wrapperTask = Task.Factory.StartNew(...);
Task actualTask = wrapperTask.Unwrap();
Task.WaitAll(actualTask);

这篇关于Task.WaitAll没有等待任务完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆