异步编程和循环中的await
本文关键字:await 循环 编程 异步 | 更新日期: 2023-09-27 17:53:51
我开始用c# 5和。net 4.5学习异步编程,有些东西我不明白。
private static int count;
public static void Main()
{
LoopTest();
Console.ReadKey(false);
}
static async void LoopTest()
{
count = 0;
for (var index = 0; index < 10; ++index)
{
Console.WriteLine( "({0}) In Loop before await, Index {1}, Thread: {2}", count++, index, Thread.CurrentThread.ManagedThreadId);
await Task.Factory.StartNew(() => Thread.Sleep(10));
}
}
结果是:
(0) In Loop before await, Index 0, Thread: 9
(1) In Loop before await, Index 1, Thread: 10
(2) In Loop before await, Index 2, Thread: 11
(3) In Loop before await, Index 3, Thread: 10
(4) In Loop before await, Index 4, Thread: 11
(5) In Loop before await, Index 5, Thread: 10
(6) In Loop before await, Index 6, Thread: 12
(7) In Loop before await, Index 7, Thread: 11
(8) In Loop before await, Index 8, Thread: 10
(9) In Loop before await, Index 9, Thread: 12
那么是否有不同的线程访问同一个循环?在索引变量上有一个竞争条件吗?
不存在竞争条件。你启动一个新任务,它将在后台运行,但你的代码将不会继续,直到该任务完成,所以你可以确保你的代码在任何时候都只在一个线程中执行。
但是,因为这是一个控制台应用程序,所以没有当前的SyncronizationContext
。(与winform, WPF, ASP, Silverlight等应用程序相反,在这些应用程序中会有。)这意味着任何await
调用的延续都将在线程池中运行,而不是在调用线程中运行。所以,是的,在循环的每次迭代中,您都运行在线程池线程中的一个线程中,并且每次都可能是不同的线程,但是您可以确定,除了您放入新任务中的任何内容外,您将在开始处理下一个线程之前"完成"在任何给定线程上的运行,这确保在任何给定时间只有一个线程运行代码(这意味着没有竞争条件)。
你所做的并不是真正异步的
await Task.Factory.StartNew(() => Thread.Sleep(10));
创建一个任务,然后等待该任务完成。你不妨在这里直接调用Thread.Sleep(10)。
更合适的方式是:
Task myTask = Task.Factory.StartNew(() => Thread.Sleep(10));
... do stuff here ...
await myTask; // Now wait for the task to complete
如果你想在一个循环中执行多个任务,你应该看看Parallel.Foreach()
方法。