2015-10-23 3 views
3

Мой объект Controller вызывает вызовы в MySQL DB через SSH с использованием Renci.SshNet, так как я подключаюсь к нескольким БД, я обратился к многопоточности, функция af.FetchAll() возвращает DataSet, все из которых добавляются в список DataList<DataSet>, тогда попросите все задачи завершить, затем я дам свой DataList объекту-писателю, чтобы сохранить его в CSV-файле. Проблема в том, что код внутри awaiter.OnCompleted(() =>..etc все еще обновляет DataList, пока автор файла пытается получить к нему доступ, несмотря на то, что я спрашиваю задача завершить foreach (Task t in taskList) t.Wait();, как я могу убедиться, что awaiter окончания выполнения, прежде чем я пойти и написать «DataList» в файлКогда вы вызываете `OnCompleted()` на awaiter задачи C#, как вы ждете нового задания, указанного внутри вызова OnCompleted?

public void Query() 
    { 
     List<QueryValue> QueriesList = quryValLister.GetQueriesList(); 
     List<ConnectionValues> ConnectionsList = concValLister.GetConnectionList(); 
     // iterating over servers 
     List<Task> taskList = new List<Task>(); 
     foreach (ConnectionValues obj in ConnectionsList) 
     { 
      Controller af = new Controller(obj, QueriesList); 
      Task<DataSet> taskDataResult = Task.Run (() => af.FetchAll()); 
      taskList.Add(taskDataResult); 
      var awaiter = taskDataResult.GetAwaiter(); 
      awaiter.OnCompleted(() => 
      { 
       DataSet temp = awaiter.GetResult(); 
       if (temp != null) 
       { 
        MyDataList.Add(temp); 
       } 

      }); 
     } 
     foreach (Task t in taskList) t.Wait(); 
    } 
+1

Почему вы используете 'GetAwaiter' вообще? Почему бы не «подождать»? –

ответ

6

Вы не должны потреблять GetAwaiter в обычном коде.

Если вы хотите, чтобы написать это асинхронно, вы можете сделать это:

public Task QueryAsync() 
{ 
    List<QueryValue> QueriesList = quryValLister.GetQueriesList(); 
    List<ConnectionValues> ConnectionsList = concValLister.GetConnectionList(); 
    // iterating over servers 
    var tasks = ConnectionsList 
     .Select(obj => Task.Run(() => new Controller(obj, QueriesList).FetchAll())); 
    MyDataList.AddRange(await Task.WhenAll(tasks)); 
} 

Или, если вы хотите записать его синхронно:

public void Query() 
{ 
    List<QueryValue> QueriesList = quryValLister.GetQueriesList(); 
    List<ConnectionValues> ConnectionsList = concValLister.GetConnectionList(); 
    // iterating over servers 
    var tasks = ConnectionsList 
     .Select(obj => Task.Run(() => new Controller(obj, QueriesList).FetchAll())) 
     .ToArray(); 
    Task.WaitAll(tasks); 
    foreach (var task in tasks) 
    MyDataList.Add(task.Result); 
} 

Обратите внимание, что обработка ошибок отличается в синхронная версия; исключения завернуты в AggregateException.

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