1

Имеется код:

var Tasks = new List<Task>();

foreach (string el in OFD.FileNames)
{
    Tasks.Add(Task.Factory.StartNew(() => performFFT(Id, buffer)));
}

while (Tasks.Count > 0)
{
    int index = Task.WaitAny(Tasks.ToArray());
    Tasks.RemoveAt(index);
    progressBar.PerformStep();
}

Как выполнить все таски в фоне?

т.к. становится недоступной главная форма

andreycha
  • 25,167
  • 4
  • 46
  • 82

2 Answers2

3

Самый простой способ такой. Таски на самом деле уже начинают выполняться в тот момент, когда вы вызываете Task.Run() (если вам не нужны дополнительные параметры на запуске, это менее многословный способ запуска, нежели Task.Factory.StartNew()). Дальше мы лишь дожидаемся их выполнения.

var Tasks = new List<Task>();

foreach (string el in OFD.FileNames)
{
    Tasks.Add(Task.Run(() => performFFT(Id, buffer)));
}

while (Tasks.Count > 0)
{
    int index = await Task.WhenAny(Tasks.ToArray());
    Tasks.RemoveAt(index);
    progressBar.PerformStep();
}

Однако более каноничным с т.з. паттерна TAP будет использование Task.WhenAll() и Progress<T> (он запоминает контекст, в котором был создан, и репорты выполняет в нем).

var Tasks = new List<Task>();
var progress = new Progress<int>(i => progressBar.PerformStep());

foreach (string el in OFD.FileNames)
{
    Tasks.Add(Task.Run(() => performFFT(Id, buffer, progress)));
}

await Task.WhenAll(Tasks);

...

private void performFFT(..., IProgress<int> progress)
{
    // делаем работу
    progress.Report(0); //параметр в вашем случае неважен 
}
andreycha
  • 25,167
  • 4
  • 46
  • 82
  • Всмысле каноничным? Есть разница? – zaki hatfild Apr 22 '16 at 10:37
  • Иии да, Ошибка: Оператор await можно использовать только в методах с модификатором async. Попробуйте пометить этот метод модификатором async и изменить тип его возвращаемого значения на Task. – zaki hatfild Apr 22 '16 at 10:41
2

Если вы используете .NET 4.5 и старше, то проще всего решить эту задачу через асинхронный код.

private async Task m()
{
    var Tasks = new List<Task>();

    foreach (string el in OFD.FileNames) {
        Tasks.Add(Task.Factory.StartNew(() => performFFT(Id, buffer)));
    }

    while (Tasks.Count > 0) {
        var task = await Task.WhenAny(Tasks.ToArray());
        Tasks.Remove(task);
        progressBar.PerformStep();
    }
}
kmv
  • 6,159
  • Мне бы просто ещё сдвигать ползунок прогресса progressBar.PerformStep(); после каждого выполненного таска – zaki hatfild Apr 22 '16 at 09:34
  • @zakihatfild ну тогда используйте WhenAny в цикле, также как делали раньше. – Pavel Mayorov Apr 22 '16 at 09:38
  • @zakihatfild либо используйте Progress<int> (этосчитается более каноничным с т.з. TAP). Его нужно передавать в метод performFFT, пример можно посмотреть тут. – andreycha Apr 22 '16 at 09:39
  • что в using прописать для async? – zaki hatfild Apr 22 '16 at 09:41
  • 1
    Нужно чтобы таски выполнялись параллельно. await разве не будет дожидаться выполнения каждого таска? – zaki hatfild Apr 22 '16 at 09:44
  • Исправил код, таски запускаются параллельно, после завершения каждого таска обновляется прогресс бар. Чтобы асинхронный код работал, проект должен использовать .NET 4.5 и старше, VS 2012 и старше. В using достаточно System.Threading.Tasks. – kmv Apr 22 '16 at 10:09