前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C# Task 使用 WhenAll 和 WaitAll 需要注意的坑

C# Task 使用 WhenAll 和 WaitAll 需要注意的坑

作者头像
晓晨
发布2022-05-07 19:07:20
1.2K0
发布2022-05-07 19:07:20
举报
文章被收录于专栏:晓晨的专栏晓晨的专栏

1.无限等待

我们在使用 WhenAll 和 WaitAll 时,一定得要注意:

1.必须添加超时时间,防止无限等待

2.等待的 Task 一定要保证是启动的。

比如下面这种写法:

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace TaskForWhenAll
{
    class Program
    {
        static void Main(string[] args)
        {
            var taskList = new List<Task>();
            for (int i = 0; i < 5; i++)
            {
                taskList.Add(new Task(() =>
                {
                    Console.WriteLine("Task {0} is finished", Task.CurrentId);
                }));
            }

            // await Task.WhenAny(taskList);
            Task.WaitAll(taskList.ToArray());
            Console.WriteLine("exit");
        }
    }
}

将不会正常运行,会一直无限等待,因为 new Task 这样创建出来的 Task 不会自动运行,需要手动调用 Task.Start

改造一下代码:

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace TaskForWhenAll
{
    class Program
    {
        static void Main(string[] args)
        {
            var taskList = new List<Task>();
            for (int i = 0; i < 5; i++)
            {
                taskList.Add(Task.Run(() =>
                {
                    Console.WriteLine("Task {0} is finished", Task.CurrentId);
                }));
            }

            // await Task.WhenAny(taskList);
            Task.WaitAll(taskList.ToArray());
            Console.WriteLine("exit");
        }
    }
}

使用 Task.Run 创建的 Task 是会自动运行的

2.没有期望的等待

我们在创建 Task 时,可能会定义一个异步委托,以便方便在 Task 里面使用 await,例如:

代码语言:javascript
复制
class Program
{
    static async Task Main(string[] args)
    {
        var taskList = new List<Task>();
        for (int i = 0; i < 5; i++)
        {
            taskList.Add(Task.Factory.StartNew(async () =>
            {
                await Task.Delay(3000);
                Console.WriteLine("Task {0} is finished", Task.CurrentId);
            }));
        }

        await Task.WhenAny(taskList);
        Console.WriteLine("exit");
    }
}

直接运行会发生什么

直接就退出了,并没有等待所有任务执行完毕。

我们换成 Task.Run 是可以正常运行的,这是为什么呢?这是因为我们这种写法,会把 Task Result 包装一层,我们需要得到期望的结果需要解除包装 UnWrap,Task.Factory.StartNew和Task.Run区别之一就有Task.Run会自动执行Unwrap操作。

我们改造一下代码

代码语言:javascript
复制
taskList.Add(Task.Factory.StartNew(async () =>
                {
                    await Task.Delay(3000);
                    Console.WriteLine("Task {0} is finished", Task.CurrentId);
                }).Unwrap());

就能按照我们期望的去运行

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-03-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.无限等待
  • 2.没有期望的等待
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档