如何使用异步方法正确编写Parallel.For

时间:2013-10-09 22:55:59

标签: c# .net task-parallel-library async-await

如何构造下面的代码以便调用异步方法?

Parallel.For(0, elevations.Count(), delegate(int i)
{
   allSheets.AddRange(await BuildSheetsAsync(userID, elevations[i], includeLabels));
});

4 个答案:

答案 0 :(得分:31)

Parallel.For()async方法不兼容。如果您不需要限制并行度(即,您可以同时执行所有任务),则只需启动所有Task,然后等待它们完成:

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();

答案 1 :(得分:4)

我建议你看一下我几天前提出的这个问题并最终回答自己,基本上我正在寻找一个并行和异步ForEach方法

该方法使用SemaphoreSlim并行处理事物,并接受异步方法作为输入操作。

您可能还想查看我在答案结尾处提供的两个链接,它们对实现此类行为非常有用,并且它们还包含使用Partitioner执行此操作的另一种方法代替。

就个人而言,我不喜欢Parallel.For,因为它是同步通话,正如我给出的链接所解释的那样;我希望它全部'异步': - )

这是:Asynchronously and parallelly downloading files

答案 2 :(得分:0)

您可以尝试使用我正在使用的这段代码。它使用foreach和SemaphoreSlim来实现并行异步。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from nsepy import get_history
import datetime as dt
%matplotlib inline
start = dt.datetime(2015, 1, 1)
end = dt.datetime.today()
infy = get_history(symbol='INFY', start = start, end = end)
infy.index = pd.to_datetime(infy.index)
hdfc = get_history(symbol='HDFC', start = start, end = end)
hdfc.index = pd.to_datetime(hdfc.index)
reliance = get_history(symbol='RELIANCE', start = start, end = end)
reliance.index = pd.to_datetime(reliance.index)
wipro = get_history(symbol='WIPRO', start = start, end = end)
wipro.index = pd.to_datetime(wipro.index)
open_prices = pd.concat([infy['Open'], hdfc['Open'],reliance['Open'], 
wipro['Open']], axis = 1)
open_prices.columns = ['Infy', 'Hdfc', 'Reliance', 'Wipro']
f, (ax1, ax2) = plt.subplots(1, 2, sharey=True)
axes[0, 0].plot(open_prices.index.year,open_prices.INFY)
axes[0, 1].plot(open_prices.index.year,open_prices.HDB)
axes[1, 0].plot(open_prices.index.year,open_prices.TTM)
axes[1, 1].plot(open_prices.index.year,open_prices.WIT)

用法:

brew install chargepoint/xcparse/xcparse

任何建议请让我知道。

答案 3 :(得分:-2)

Parallel.For中调用异步方法的最简单方法是:

Parallel.For(0, elevations.Count(), async i =>
{
   allSheets.AddRange(await BuildSheetsAsync(userID, elevations[i], includeLabels));
});

==============

MarioDS在评论中提到绝对正确,在这种情况下,您可能有未观察到的异常。这绝对是非常重要的事情,你应该始终牢记然后与异步代表达成协议。

在这种情况下,如果您认为自己有例外,可以在委托中使用try/catch阻止。或者在某些情况下,如果您的情况有利,您可以订阅TaskScheduler.UnobservedTaskException事件。