我将如何构造下面的代码以便调用异步方法?
Parallel.For(0, elevations.Count(), delegate(int i)
{
allSheets.AddRange(await BuildSheetsAsync(userID, elevations[i], includeLabels));
});
我将如何构造下面的代码以便调用异步方法?
Parallel.For(0, elevations.Count(), delegate(int i)
{
allSheets.AddRange(await BuildSheetsAsync(userID, elevations[i], includeLabels));
});
Parallel.For()
不适用于async
方法。如果您不需要限制并行度(即您可以同时执行所有任务),您可以简单地启动所有Task
s 然后等待它们完成:
var tasks = Enumerable.Range(0, elevations.Count())
.Select(i => BuildSheetsAsync(userID, elevations[i], includeLabels));
List<Bitmap> allSheets = (await Task.WhenAll(tasks)).SelectMany(x => x).ToList();
我建议你看看我几天前问的这个问题,最后回答了自己,基本上我在寻找一个并行和异步的 ForEach 方法。
该方法用于SemaphoreSlim
并行处理事物,它接受异步方法作为输入操作。
您可能还想查看我在答案末尾提供的两个链接,它们对于实现这种行为非常有帮助,并且它们还包含另一种使用 aPartitioner
来执行此操作的方法。
就个人而言,我不喜欢它,Parallel.For
因为它是我给出的链接中解释的同步调用;我想要这一切'异步':-)
这里是:异步和并行下载文件
你可以试试我正在使用的这段代码。它使用 foreach 和 SemaphoreSlim 来实现并行异步。
public static class ParallelAsync
{
public static async Task ForeachAsync<T>(IEnumerable<T> source, int maxParallelCount, Func<T, Task> action)
{
using (SemaphoreSlim completeSemphoreSlim = new SemaphoreSlim(1))
using (SemaphoreSlim taskCountLimitsemaphoreSlim = new SemaphoreSlim(maxParallelCount))
{
await completeSemphoreSlim.WaitAsync();
int runningtaskCount = source.Count();
foreach (var item in source)
{
await taskCountLimitsemaphoreSlim.WaitAsync();
Task.Run(async () =>
{
try
{
await action(item).ContinueWith(task =>
{
Interlocked.Decrement(ref runningtaskCount);
if (runningtaskCount == 0)
{
completeSemphoreSlim.Release();
}
});
}
finally
{
taskCountLimitsemaphoreSlim.Release();
}
}).GetHashCode();
}
await completeSemphoreSlim.WaitAsync();
}
}
}
用法:
string[] a = new string[] {
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"20"
};
Random random = new Random();
await ParallelAsync.ForeachAsync(a, 2, async item =>
{
Console.WriteLine(item + " start");
await Task.Delay(random.Next(1500, 3000));
Console.WriteLine(item + " end");
});
Console.WriteLine("All finished");
任何建议请告诉我。
在内部调用异步方法的最简单方法Parallel.For
是:
Parallel.For(0, elevations.Count(), async i =>
{
allSheets.AddRange(await BuildSheetsAsync(userID, elevations[i], includeLabels));
});
===============
MarioDS在评论中绝对正确地提到,在这种情况下,您可能会有未观察到的异常。这绝对是非常重要的事情,您应该始终牢记这一点,然后处理异步委托。
在这种情况下,如果您认为您会遇到异常,您可以try/catch
在委托中使用块。或者在某些情况下,如果您的情况适合,您可以订阅TaskScheduler.UnobservedTaskException事件。