Выполнение задач из списка - PullRequest
0 голосов
/ 26 марта 2020

Я пытаюсь запустить Список задач, используя следующий метод:

List<Task> tasks = new List<Task>();

tasks.Add(new Task(() => this.firstMethod()));
tasks.Add(new Task(() => this.secondMethod()));

Однако, если я использую один из двух примеров ниже, я получаю следующие проблемы:

foreach (Task task in tasks)
{
    await Task.Run(() => task);
}

В этом первом случае задачи вообще не запускаются.

foreach (Task task in tasks)
{
    task.Start();
    task.Wait();
}

Во втором случае он запускается только один раз, и я получаю следующую ошибку:

Запуск не может быть вызван для задачи, которая завершилась

Чего мне не хватает?

Ответы [ 3 ]

2 голосов
/ 26 марта 2020

Вы не можете повторно использовать задачу. Итак, начнем с создания массива делегатов

List<Action> tasks = new List<Action>();

tasks.Add(this.firstMethod);
tasks.Add(this.secondMethod);

, а затем запускаем их последовательно в дополнительных потоках (оставляя основной поток свободным для обновления пользовательского интерфейса):

foreach (Action task in tasks)
{
    await Task.Run(task);
}

, но это l oop может быть сделано разными способами, в зависимости от контекста вызывающего кода и характера полезных нагрузок.

Это может быть не лучшим решением.

2 голосов
/ 26 марта 2020

Вот модульный тест, который показывает, как вы можете это сделать:

    public class TasksTests
    {
        private readonly ITestOutputHelper _output;

        public TasksTests(ITestOutputHelper output)
        {
            _output = output ?? throw new ArgumentNullException(nameof(output));
        }

        [Fact]
        public async Task CanCreateAndRunTasks()
        {
            var tasks = new List<Task>
            {
                new Task(() => _output.WriteLine("Task #1")),
                new Task(() => _output.WriteLine("Task #2"))
            };

            tasks.ForEach(t => t.Start());

            await Task.WhenAll(tasks);
        }
    }

Сначала вы создаете задачи. Тогда вам нужно их запустить. И, наконец, вам нужно дождаться их всех, например, используя Task.WhenAll.

0 голосов
/ 26 марта 2020

первый пример дела

foreach (Task task in tasks)
{
    await Task.Run(() => task);
}

должен быть изменен на

foreach (Task task in tasks)
{
    task.Start(); // there is no sense to await since tasks should be run in parallel I suppose
}

Однако второй случай неясен. Вы запускаете второй случай после первого? Хорошо, если у вас tasks только что инициализирован перед вызовом Start, как

List<Task> tasks = new List<Task>()
{
new Task(() => this.firstMethod()),
new Task(() => this.secondMethod()),
};
foreach (Task task in tasks)
{
    task.Start();
    task.Wait(); // this causes tasks to be run in sequence (one by one) like with await in the first sample
}

. Самый простой случай - использовать Task.Run

var tasks = new[Task]
{
Task.Run(firstMethod),
Task.Run(secondMethod),
}; // tasks are started immediately there is no need to start them later

Task.WaitAll(tasks); // wait until all tasks are finished

...