Это расширение моих комментариев под вопросом
По существу, progress обычно является значением только для форварда. Что касается сообщения о прогрессе , вполне вероятно, что вам никогда не нужно сообщать о прогрессе, достигнутом в прошлом. Даже если вы это сделаете, в большинстве случаев клиент / обработчик событий будет по-прежнему отбрасывать полученные значения.
Проблема в том, почему вам нужно синхронизировать отчеты, главным образом потому, что вы сообщаете о прогрессе типа значения, значение которого копируется при вызове Report(T)
.
Вы можете просто избежать блокировки, сообщив экземпляр ссылочного типа с последним достигнутым прогрессом:
public class DoStuffProgress
{
private volatile int _percentage;
public int Percentage => _percentage;
internal void IncrementBy(int increment)
{
Interlocked.Add(ref _percentage, increment);
}
}
Теперь ваш код выглядит следующим образом:
async Task DoStuffAsync(IProgress<DoStuffProgress> progress)
{
DoStuffProgress totalPercentDone = new DoStuffProgress();
Task[] tasks = Enumerable.Range(1, 2).Select(n => Task.Run(async () =>
{
for (int i = 0; i < 5; i++)
{
await Task.Delay(100); // Simulate an I/O operation
totalPercentDone.IncrementBy(10);
// Report reference type object
progress.Report(totalPercentDone);
}
})).ToArray();
await Task.WhenAll(tasks);
}
Однако клиент может получить уведомление с повторяющимся значением:
Progress: 20
Progress: 20
Progress: 40
Progress: 40
Progress: 60
Progress: 60
Progress: 80
Progress: 80
Progress: 90
Progress: 100
Но значения никогда не должны быть не в порядке.