2016-07-16 2 views
0

У меня есть некоторые проблемы с Task.Factory.StartNew и Task.WaitAll. Задачи начинаются так, как они должны, но похоже, что они просто игнорируют Task.WaitAll, потому что после нажатия на кнопку (это событие, в котором этот код находится) MessageBox уже всплывает.Task.Factory.StartNew игнорирует Task.WaitAll

List<Task> tasks = new List<Task>(); 
     if (plugin.UseProxy) 
     { 
      foreach (var item in combo) 
      { 
       Task.Factory.StartNew(() => 
       { 
        // Some code 
       }).ContinueWith((t) => 
       { 
        tasks.Add(t); 
        pbProgress.Value++; 

       }, TaskScheduler.FromCurrentSynchronizationContext()); 
      } 
     } 
     else 
     { 
      foreach (var item in combo) 
      { 
       Task.Factory.StartNew(() => 
       { 
        // Some code 
       }).ContinueWith((t) => 
       { 
        tasks.Add(t); 
        pbProgress.Value++; 

       }, TaskScheduler.FromCurrentSynchronizationContext()); 
      } 
     } 

     Task.WaitAll(tasks.ToArray()); 
     MessageBox.Show("Hello"); 
+0

Потому что ваш список 'tasks' пуст в тот момент, когда вы выполняете' Task.WaitAll' – Fabio

ответ

2

Вы только добавляете Задачи в свой список, когда закончите. ContinueWith выполняет, когда задача выполнена. Итак, Task.WaitAll ждет пустой список задач.

Таким образом, вы можете сделать это:

Task task = Task.StartNew(() => 
{ 
    // Some code 
}).ContinueWith((t) => 
{ 
    pbProgress.Value++; 
}, TaskScheduler.FromCurrentSynchronizationContext()); 

tasks.Add(task); 
0

tasks список только получить элементы, добавленные к нему после того, как поток начал через StartNew отделки. Проблема, с которой вы сталкиваетесь, - это поразить Task.WaitAll(tasks.ToArray());, прежде чем элементы будут добавлены в коллекцию. Вам нужно добавить элементы в коллекцию в потоке, который их создает, а не в продолжать,

var newTask = Task.Factory.StartNew(() => 
{ 
    // Some code 
}); 
tasks.Add(newTask); 
newTask.ContinueWith((t) => 
{ 
    pbProgress.Value++; 

}, TaskScheduler.FromCurrentSynchronizationContext()); 

Однако ваш код и другие проблемы. Вы никогда не переходите на завод TaskSchedueller, если вы не можете easily accidentally start your thread on the UI thread. Также я предполагаю, что этот код работает в потоке пользовательского интерфейса, ваш Task.WaitAll заблокирует поток пользовательского интерфейса. Это может привести к взаимоблокировкам, если один из этих потоков StartNew оказался в потоке пользовательского интерфейса.

+0

Я вижу спасибо. Как я могу избежать взаимоблокировок с Task.WaitAll? – ioncodes

+0

Новая тема (() => { Task.WaitAll (tasks.ToArray()); MessageBox.Show («Hello»); }); Я делаю это, и мой пользовательский интерфейс больше не замерзает. Но теперь мой MessageBox больше не появляется. XD – ioncodes

+0

Используя async/await и 'Tasks.WhenAll'. Перейдите к основному учебнику по асинхронному обследованию. –

Смежные вопросы