По вашему вопросу, Progress только вызывает. Это зависит от кода, который вы написали для обработки прогресса на другой стороне. Я бы сказал, что строка progress.Report(totalSteps * System.Threading.Interlocked.Increment(ref currentStep) * .1f);
может вызвать потенциальную проблему с отчетами о прогрессе из-за умножения, не являющегося атомом c.
Это то, что происходит внутри Progress, когда вы вызываете Report * 1005. *
protected virtual void OnReport(T value)
{
// If there's no handler, don't bother going through the sync context.
// Inside the callback, we'll need to check again, in case
// an event handler is removed between now and then.
Action<T> handler = m_handler;
EventHandler<T> changedEvent = ProgressChanged;
if (handler != null || changedEvent != null)
{
// Post the processing to the sync context.
// (If T is a value type, it will get boxed here.)
m_synchronizationContext.Post(m_invokeHandlers, value);
}
}
Тем не менее, в коде лучший способ работать параллельно - использовать PLinq. В вашем текущем коде, если список содержит много элементов, он будет раскручивать задачи для каждого элемента одновременно и ждать завершения всех из них. Однако в PLinq количество одновременных выполнений будет определяться для оптимизации производительности.
myElements.AsParallel().ForAll(async elem =>
{
var result = await SomeHeavyApiCall(elem);
DoSomethingWithThe(result);
progress.Report(totalSteps * System.Threading.Interlocked.Increment(ref currentStep) * .1f);
}
Помните, что AsParallel (). ForAll () немедленно вернется при использовании asyn c fun c. Поэтому вам может потребоваться захватить все задачи и дождаться их, прежде чем продолжить.
И последнее: если ваш список редактируется во время его обработки, я рекомендую использовать ConcurrentQueue или ConcurrentDictionary или ConcurrentBag.