我从这里阅读了这条指南http://blog.stephencleary.com/2012/02/async-and-await.html
这里我有几个代码,但对我来说不是很清楚。
1)
public async Task DoOperationsInParallelAsync()
{
Task[] tasks = new Task[3];
tasks[0] = DoOperation0();
tasks[1] = DoOperation1();
tasks[2] = DoOperation2();
// At this point, all three tasks are running in parallel.
// Now, we await them all.
await Task.WhenAll(tasks);
}
在上面我们创建了多个任务但是假设当所有任务都并行运行时,DoOperation2()可能首先完成,DoOperation0()和DoOperation1()完成。如果我想在控制台窗口中显示像DoOperation2()这样的消息,那么我该怎么做呢。如何在多个运行时检测到哪个任务完成。
2)当我们在 async / await 的帮助下运行任何函数时,它是作为后台线程还是前台线程运行的。
3)
public async Task<int> GetFirstToRespondAsync()
{
// Call two web services; take the first response.
Task<int>[] tasks = new[] { WebService1(), WebService2() };
// Await for the first one to respond.
Task<int> firstTask = await Task.WhenAny(tasks);
// Return the result.
return await firstTask;
}
我不明白为什么这个人写了等待第一个回复。
//等待第一个回复。 任务firstTask = await Task.WhenAny(tasks);
为什么第一个......为什么不是第二个因为两个任务在这里运行。
请指导我并消除我的困惑。感谢
答案 0 :(得分:1)
您可以对将更新进度的每个任务使用ContinueWith方法。
因此...
foreach (var t in tasks)
{
t.ContinueWith(Console.WriteLine("Hey I am done"));
}
答案 1 :(得分:1)
1)传入回调函数
public async Task DoOperationsInParallelAsync(Action<Task<int>> completed)
{
var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
var tasks = new[] { DoOperation0(), DoOperation1(), DoOperation2() };
var completedTasks = tasks.Select(x => x.ContinueWith(completed, uiScheduler)).ToArray();
await Task.WhenAll(completedTasks);
}
private async void Button1_Click(object sender, EventArgs e)
{
await DoOperationsInParallelAsync(t => {
Label1.Text = string.Format("Task finished with {0}", t.Result);
});
}
2)Task
将在线程池上运行,除非您将其指定为长时间运行或提供TaskScheduler
。
3)当只有第一个结果很重要(计算是多余的或时间敏感的)时,例如从各个供应商那里获取反映相似数据的股票价格。
答案 2 :(得分:1)
因为它是一个控制台应用程序,您需要等待任务完成。以下是如何从任务返回字符串的示例:
class WhenAny
{
public static async Task<string> GetFirstToRespondAsync()
{
// Call two web services; take the first response.
Task<string>[] tasks = new[] { Task1(), Task2() };
// Await for the first one to respond.
Task<string> firstTask = await Task.WhenAny(tasks);
// Return the result.
return firstTask.Result;
}
private static async Task<string> Task1()
{
await Task.Delay(3000);
return "Task1";
}
private static async Task<string> Task2()
{
await Task.Delay(1000);
return "Task2";
}
}
从Main函数调用它,如下所示:
static void Main(string[] args)
{
var t = WhenAny.GetFirstToRespondAsync();
t.ContinueWith((taskName) =>
{
string result = taskName.Result;
Console.WriteLine("Result: " + result);
});
t.Wait();
Console.ReadLine();
}
这应该返回首先完成的任务,您可以从Task.Result
等待方法本身不会创建一个额外的线程。它的作用是创建一个回调以避免阻塞当前线程(通常这用于不阻止UI线程)。
WhenAny
在最早完成的操作返回时返回。这并不意味着您提供的列表中的第一个。因此,上面的代码将始终显示1000,即使这是第二个任务。
为了完整性,这与WhenAll:
是一回事class WhenAll
{
public static async Task<string[]> WaitForAllAsync()
{
// Call two web services; take the first response.
Task<string>[] tasks = new[] { Task1(), Task2(), Task3() };
// Wait for a tasks
string[] results = await Task.WhenAll(tasks);
// Return the result.
return results;
}
private static async Task<string> Task1()
{
await Task.Delay(3000);
return "Task1";
}
private static async Task<string> Task2()
{
await Task.Delay(1000);
return "Task2";
}
private static async Task<string> Task3()
{
await Task.Delay(5000);
return "Task3";
}
}
并称之为:
static void Main(string[] args)
{
var t = WhenAll.WaitForAllAsync();
t.ContinueWith((task) =>
{
string[] result = task.Result;
foreach(string taskname in result)
{
Console.WriteLine("Result: " + taskname);
}
});
t.Wait();
Console.ReadLine();
}