【问题标题】:Threading.Tasks: Concept of WaitAll()Threading.Tasks:WaitAll() 的概念
【发布时间】:2012-05-19 02:21:13
【问题描述】:

我在 控制台 应用程序(不确定这是否与此有关)和使用任务时遇到了一个奇怪的问题。

大多数示例显示故意调用异常来测试/解释 WaitAll 的概念 - 但在我的情况下,似乎我在做一些根本错误的事情(或不完全理解)。

Task<int> task1 = Task<int>.Factory.StartNew(()=> foo(arg));
Task<int> task2 = Task<int>.Factory.StartNew(()=> bar(arg));

Task<int>[] tasks = {task1, task2};

try
{
    Task.WaitAll(tasks); //hits this far

     if((int)task1.Result * (int)task2.Result == 99) //this seems to never get hit
     {
         System.Environment.Exit(0); //so this isn't called             
     }
     else
     {
         System.Environment.Exit(1); // neither is this called
     }
 }
 catch
 {
     .....

在上面看来,if 块没有被击中,所以没有返回退出代码 - 因此控制台应用程序挂起。

也没有抛出异常 - 我可以确认这一点,因为所有任务实际上都已完成 - 为了简洁起见,我只是没有包括上面的 catch 部分。

任务很快完成 - 它们没有挂起,所以它不像 Task.WaitAll 仍在等待 - 或者它可能是,这就是我错过的东西(它在等待什么)?

有任何想法、建议或残酷的更正吗?谢谢!

【问题讨论】:

  • 我们需要更多地了解这些任务。您对 WaitAll 的理解是正确的,它要么在任务完成时返回,要么在任何任务中抛出异常。 (请注意,只有在所有任务完成后才会抛出异常)
  • sn-p 确实需要证明 foo 或 bar 正在引发异常。否则,使用调试器诊断此问题应该没有问题,它会清楚地显示您的 catch 块被命中。
  • 附带说明,您不需要 (int) 强制转换,在您的情况下,Result 的类型已经是 (int)。
  • 谢谢大家 - 我会尽快回复您。我将通过@caesay 谈论任务挂起/不返回值 - 即使 foo 或 bar 确实做了他们需要做的事情,没有例外/已验证 - 所以我必须调查也许为什么两者都没有返回值。

标签: c# .net multithreading task-parallel-library task


【解决方案1】:

只是为了论证,我做了一个小测试(如下所示) - 它表明您的一项任务正在挂起,并且没有返回值。

        Task<int> task1 = Task<int>.Factory.StartNew(() =>
        {
            Thread.Sleep(2000);
            return 10;
        });
        Task<int> task2 = Task<int>.Factory.StartNew(() => 15);
        Task<int>[] tasks = {task1, task2};
        try
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            Task.WaitAll(tasks);
            sw.Stop();
            Console.WriteLine(String.Format("tasks completed in {0}ms", sw.ElapsedMilliseconds));
        }
        catch
        {
            Console.WriteLine("Error");
        }
        Console.ReadLine();

如果你运行它,它将打印tasks completed in 2000ms(给定或花费几毫秒)。我所做的只是复制/粘贴您的代码并添加到我自己的任务中。

所以你说"The tasks are [...] not hanging..." 是假的——他们一定是挂了。

【讨论】:

  • 谢谢,我会更深入地研究一项我可能假设已完成的任务。它涉及SSH.Net - 它做了它需要做的事情(将文件写入 SFTP 位置)但也许这个任务没有正确返回一个 int 值。
  • 谢谢 - 这实际上是问题所在。似乎有一些intermittent issue with SSH.NET Disconnect()。虽然该问题被标记为已关闭,但似乎不应该如此。 Another issue 指向听起来相关的 Disconnect()。无论如何,感谢您的帮助!
【解决方案2】:

正如上面 caesay 所解释的,任务必须是挂起的。要检查这一点,我建议为您的 WaitAll 呼叫设置默认超时时间。您可以通过传入一个 int 来做到这一点,它表示调用必须等待任务结束的毫秒数。试试这个

Task.WaitAll(tasks, 10000); //Set to wait for 10 seconds

然后看看是否有异常或者你的“if”语句是否被命中。如果这可行,则尝试使用更大的时间间隔来查看任务的情况。

另外,我建议运行 foo 和 bar 中没有任务(即顺序)的代码作为测试工具,以了解这两个示例方法是否存在任何特定问题。

【讨论】:

  • 感谢您的建议。这可能无法解决,因为我正在等待返回值 - re:因此它总是“失败”即使他们实际执行了任务。我知道这听起来很奇怪——但就我而言,任务确实完成了。由于某种原因,它们中的任何一个(或两个)都没有返回值(我已经在第 3 方开源库中有嫌疑人)。
  • 因此,当您说“任务确实完成无异常”时,必须命中 if 块,因为它是执行模型中的下一个逻辑语句。您是在暗示“if”语句永远不会执行,还是会执行但任务没有返回值?
  • 感谢您的建议!发现并解决了问题。 if 不会间歇性运行(lib 问题 - 见上文)。任务确实部分完成(因为它不会返回值 - 我只查看任务的一部分)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-05
相关资源
最近更新 更多