c# - Task.WaitAll - 不等待?

标签 c# multithreading parallel-processing task-parallel-library

我正在努力了解任务并行库中的 Task.WaitAll(..)。

我正在使用以下代码运行测试以尝试模拟两项任务,一项运行时间(10 秒)比指定的等待时间长(10 秒),另一项运行时间少于(3 秒)超过指定的等待时间。指定的时间是 5 秒。我使用的代码如下:

Task<int>[] tasks = new Task<int>[]
{
    Task.Factory.StartNew<int>(()=>
        {
            Thread.Sleep(10000);
            return 1;
        }),
    Task.Factory.StartNew<int>(()=>
        {
            Thread.Sleep(3000);
            return 2;
        })
};

TimeSpan timeSpan = new TimeSpan(0, 0, 5);
Task.WaitAll(tasks,timeSpan);

int[] results = new int[tasks.Length];
for(int i = 0; i < tasks.Length;i++)
{
    Console.WriteLine(tasks[i].Result);
}

关于timeSpan,我也试过直接传入5000而不是timeSpan变量,但是不行。我得到以下输出:

1
2

我预计只会得到以下输出,因为另一个线程的执行时间比预期的等待时间长。

1

我是误解了这一点,还是做错了这个测试?

最佳答案

虽然 Task.Delay 是您通常想要使用的(因此您不会在 sleep 期间浪费线程),但您的问题实际上与此无关。

这里发生的事情是,当您打印出结果时,您正在访问每个任务的 Result 属性。这阻止任务完成,因此您在 WaitAll 中等待 5 秒,然后在打印出 10 秒任务的结果时再等待 5 秒。

根据您陈述的意图,您需要在访问结果之前检查任务状态,因为您的意图不是阻止它,而是仅在它恰好已经完成时打印出来:

int[] results = new int[tasks.Length];
for (int i = 0; i < tasks.Length; i++)
{
    if (tasks[i].IsCompleted)
    {
        Console.WriteLine(tasks[i].Result);
    }
}

顺便说一句,您可以通过添加一些简单的时间检查(例如,像这样使用秒表)来显示“结果 block ”是原始代码中发生的事情

Task<int>[] tasks = new Task<int>[]
{
    Task.Factory.StartNew<int>(()=>
        {
            Thread.Sleep(10000);
            return 1;
        }),
    Task.Factory.StartNew<int>(()=>
        {
            Thread.Sleep(3000);
            return 2;
        })
};

TimeSpan timeSpan = new TimeSpan(0, 0, 5);
var stopwatch = Stopwatch.StartNew();
Task.WaitAll(tasks, timeSpan);
Console.WriteLine("WaitAll took {0} seconds", stopwatch.Elapsed.TotalSeconds);

int[] results = new int[tasks.Length];
for (int i = 0; i < tasks.Length; i++)
{
    stopwatch = Stopwatch.StartNew();
    Console.WriteLine(tasks[i].Result);
    Console.WriteLine("Printing result took {0} seconds", stopwatch.Elapsed.TotalSeconds);
}

这会产生控制台输出:

WaitAll took 4.9996961 seconds
1
Printing result took 5.0050012 seconds
2
Printing result took 0.0004338 seconds

关于c# - Task.WaitAll - 不等待?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12320894/

相关文章:

java - 有没有办法以编程方式从 JFileChooser.showOpenDialog() 返回?

multithreading - Parallel::ForkManager 使子例程慢 1000 倍

c# - 有没有办法为 C# 库设置调用应用程序执行权限?

c# - 如何将此构造函数转换为 C#?

c# - 远程桌面连接 - C# 事件

java - 线程中的异常 "main"java.lang.ClassCastException : cannot be cast to java. util.concurrent.Callable

mysql - DataGridView 中的 VB.net BackGroundWorker 跨线程

c# - 如何将 C# 库添加到 Monaco 编辑器(代码完成)并限制可能的库?

r - 为什么 tempdir() 在 fork 集群的每个核心上给出相同的结果?

c# - 添加到集合完成时从 BlockingCollection.TakeFromAny 正常退出