我试图了解C#中的异步编程。我创建了一个只能调用一次的函数示例。例如,从大文件读取。我想创建一个查询,请求将在查询中等待,直到他们可以安全地读取文件为止。
AsyncWork aw = new AsyncWork();
Task.Run(() => {
for (int count = 0; count < 10; count++) {
aw.DoAsyncWork(count);
Console.WriteLine("request added");
}
});
Console.ReadKey();
和AsyncWork
public class AsyncWork {
int Requests = 0;
int Workers = 0;
public AsyncWork() { }
public async Task DoAsyncWork(int count) {
Requests++;
while (Workers > 0) ;
Workers++;
Requests--;
if (Workers > 1) Console.WriteLine("MORE WORKERS AT ONCE");
Console.WriteLine(count.ToString() + " Started task");
//reading from file
await Task.Delay(1000);
Console.WriteLine(count.ToString() + " Ended task");
Workers--;
}
}
我希望我会有10个请求,然后一个接一个地完成。但是输出就像:
0 Started task
request added
0 Ended task
1 Started task
request added
1 Ended task
2 Started task
request added
2 Ended task
3 Started task
request added
3 Ended task
4 Started task
request added
4 Ended task
5 Started task
request added
5 Ended task
6 Started task
request added
6 Ended task
7 Started task
request added
7 Ended task
8 Started task
request added
8 Ended task
9 Started task
request added
9 Ended task
为什么它同步运行?
答案 0 :(得分:4)
运行代码时,第一个工作程序将开始工作,然后下一个工作程序将陷入您while (Workers > 0) ;
的繁忙循环中,并且直到前一个工作程序完成后才继续进行。然后,在启动工作程序时,下一个工作程序将在其中停留,依此类推,直到循环的每个迭代。
因此,您最多只能有一个工人在工作,而一个工人将整个CPU固定在那里等待它完成。
编写异步代码时同步访问的一种正确方法是使用SemaphoreSlim
并使用WaitAsync
,这将异步等待直到可以获取信号量,而不是同步阻塞线程(并在占用线程时固定CPU),以供其他工作人员完成。它也具有可以安全地从多个线程访问的优点,这与整数 不能从多个线程进行更改不同。