Sat*_*ish 75 .net c# async-await
我正在尝试创建一个异步控制台应用程序,它可以对集合进行一些操作.我有一个版本使用并行for循环另一个版本使用async/await.我希望async/await版本的工作方式类似于并行版本,但它会同步执行.我究竟做错了什么?
class Program
{
static void Main(string[] args)
{
var worker = new Worker();
worker.ParallelInit();
var t = worker.Init();
t.Wait();
Console.ReadKey();
}
}
public class Worker
{
public async Task<bool> Init()
{
var series = Enumerable.Range(1, 5).ToList();
foreach (var i in series)
{
Console.WriteLine("Starting Process {0}", i);
var result = await DoWorkAsync(i);
if (result)
{
Console.WriteLine("Ending Process {0}", i);
}
}
return true;
}
public async Task<bool> DoWorkAsync(int i)
{
Console.WriteLine("working..{0}", i);
await Task.Delay(1000);
return true;
}
public bool ParallelInit()
{
var series = Enumerable.Range(1, 5).ToList();
Parallel.ForEach(series, i =>
{
Console.WriteLine("Starting Process {0}", i);
DoWorkAsync(i);
Console.WriteLine("Ending Process {0}", i);
});
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
Tim*_* S. 104
你使用await关键字的方式告诉C#你想要在每次通过循环时等待,这是不平行的.你可以像这样重写你的方法来做你想要的,通过存储一个Tasks 的列表,然后将await它们全部用来Task.WhenAll.
public async Task<bool> Init()
{
var series = Enumerable.Range(1, 5).ToList();
var tasks = new List<Task<Tuple<int, bool>>>();
foreach (var i in series)
{
Console.WriteLine("Starting Process {0}", i);
tasks.Add(DoWorkAsync(i));
}
foreach (var task in await Task.WhenAll(tasks))
{
if (task.Item2)
{
Console.WriteLine("Ending Process {0}", task.Item1);
}
}
return true;
}
public async Task<Tuple<int, bool>> DoWorkAsync(int i)
{
Console.WriteLine("working..{0}", i);
await Task.Delay(1000);
return Tuple.Create(i, true);
}
Run Code Online (Sandbox Code Playgroud)
SLa*_*aks 34
您的代码await在开始下一次迭代之前等待每个操作(使用)完成.
因此,您没有任何并行性.
如果要并行运行现有的异步操作,则不需要await; 你只需要得到一个Tasks 的集合并调用它Task.WhenAll()来返回一个等待所有这些的任务:
return Task.WhenAll(list.Select(DoWorkAsync));
Run Code Online (Sandbox Code Playgroud)
Vla*_*mir 10
public async Task<bool> Init()
{
var series = Enumerable.Range(1, 5);
Task.WhenAll(series.Select(i => DoWorkAsync(i)));
return true;
}
Run Code Online (Sandbox Code Playgroud)
在 C# 7.0 中,您可以对 tuple 的每个成员使用语义名称,这是Tim S.使用新语法的答案:
public async Task<bool> Init()
{
var series = Enumerable.Range(1, 5).ToList();
var tasks = new List<Task<(int Index, bool IsDone)>>();
foreach (var i in series)
{
Console.WriteLine("Starting Process {0}", i);
tasks.Add(DoWorkAsync(i));
}
foreach (var task in await Task.WhenAll(tasks))
{
if (task.IsDone)
{
Console.WriteLine("Ending Process {0}", task.Index);
}
}
return true;
}
public async Task<(int Index, bool IsDone)> DoWorkAsync(int i)
{
Console.WriteLine("working..{0}", i);
await Task.Delay(1000);
return (i, true);
}
Run Code Online (Sandbox Code Playgroud)
你也可以摆脱task. insideforeach:
// ...
foreach (var (IsDone, Index) in await Task.WhenAll(tasks))
{
if (IsDone)
{
Console.WriteLine("Ending Process {0}", Index);
}
}
// ...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
68434 次 |
| 最近记录: |