如何在控制台应用程序中从Task.WaitAll()获取返回值?

时间:2014-08-15 00:10:09

标签: c# .net task-parallel-library console-application async-await

我使用控制台应用程序作为概念证明和获取异步返回值的新需求。

我发现我需要在我的main方法中使用Task.WaitAll()来避免需要async" main()"方法,这是非法的。

我现在卡住试图弄清楚允许我使用泛型的重载,或只是返回我可以投射的对象,但是在Main()中。

3 个答案:

答案 0 :(得分:58)

您没有从Task.WaitAll获得返回值。您只能使用它等待多个任务的完成,然后从任务本身获取返回值。

var task1 = GetAsync(1);
var task2 = GetAsync(2);
Task.WaitAll(task1, task2);
var result1 = task1.Result;
var result2 = task2.Result;

如果您只有一个Task,请使用Result属性。如果任务尚未完成,它将返回您的值并阻止调用线程:

var task = GetAsync(3);
var result = task.Result;

同步等待(阻止)异步任务(“异步同步”)通常不是一个好主意,但我想这对POC来说很好。

答案 1 :(得分:28)

为了获得最佳实践,请使用新的异步处理方式。 而不是

  • Task.WaitAll使用await Task.WhenAll
  • Task.WaitAny使用await Task.WhenAny

上面的代码可以写成:

var task1 = GetAsync(1);
var task2 = GetAsync(2);
var results = await Task.WhenAll(task1, task2);
var result1 = results[0];
var result2 = results[1];

答案 2 :(得分:-2)

根据上下文和您的需要,您可以使用不同的方法,但我尝试了 i3arnon 和 alltej 的答案,并且在调试中我发现它们都有相同的问题......我运行了两个代码示例我制作的控制台应用程序。我在代码中设置了一个断点,发现在 Task.WaitAllTask.WhenAll 的执行行上。当我检查任务时,我发现它们已经运行 - 任务属性 Status 是 = ran to completion。事实上,我能够完全删除 Task. 行代码并仍然分配变量值,所以它没有用。

我发现真正让这种操作按需要运行并获得所需的返回值是一项非常困难的任务。这是我想出的:

Task[] taskArray = {
    Task.Factory.StartNew(() => ExecuteConcurrentTasks(1).Result),
    Task.Factory.StartNew(() => ExecuteConcurrentTasks(2).Result)
};
Task.WaitAll(taskArray);
var s = ((Task<string>)taskArray[0]).Result;

这是一个简单的示例,其中创建了一个任务数组,然后使用 Task.WaitAll 同时执行 2 个任务,然后在最后一行中我将展示如何访问第一个任务的返回值。

这是包含更多上下文和更多数据的代码:

private static async void MyAsyncMethod()
{
    Task[] taskArray = {
        Task.Factory.StartNew(() => ExecuteConcurrentTasks(1).Result),
        Task.Factory.StartNew(() => ExecuteConcurrentTasks(2).Result),
        Task.Factory.StartNew(() => ExecuteConcurrentTasks(3).Result),
        Task.Factory.StartNew(() => ExecuteConcurrentTasks(4).Result)
    };
    Task.WaitAll(taskArray);
    string s1 = ((Task<string>)taskArray[0]).Result;
    string s2 = ((Task<string>)taskArray[1]).Result;
    string s3 = ((Task<string>)taskArray[2]).Result;
    string s4 = ((Task<string>)taskArray[3]).Result;
}



private static async Task<string> ExecuteConcurrentTasks(int passedInt)
{
    string s = "Result: " + passedInt.ToString();

    if (passedInt == 4)
    {
        Console.WriteLine(s);
    }
    else if (passedInt == 3)
    {
        Console.WriteLine(s);
    }
    else if (passedInt == 2)
    {
        Console.WriteLine(s);
    }
    else if (passedInt == 1)
    {
        Console.WriteLine(s);
    }

    return s;
}

输出如下:

output