2017-02-17 3 views
0

У меня есть случай есть я хочу, чтобы вызвать один метод ASYN внутри цикла paralle.ForeachПроблемы с вызовом метода асинхронного внутри метода Parallel.ForEach

public void ItemCheck<T>(IList<T> items,int id) 
      {  
       Parallel.ForEach(items, (current) => 
      { 
       PostData(current,id); 
      }); 
      Console.log("ItemCheck executed") 
    } 
    public async void PostData<T>(T obj, int id) 
     { 
     Console.lgo("PosstData executed") 
     } 

Выход:

ItemCheck executed 
PosstData executed 

Почему это происходит, как это ?? Перед завершением выполнения PostData метода, следующая строка executed.How я могу решить эту issue.Anyone помощь по этому

+6

Я подозреваю, что это не ваш * фактический * код. Пожалуйста, опубликуйте [mcve]. Но принципиально, ваш метод асинхронный недействителен, что затрудняет ожидание завершения всех задач перед продолжением. Кроме того, использование 'Parallel.ForEach' кажется бессмысленным, когда вы используете методы async - просто вызовите все методы async, а затем дождитесь завершения всех задач (когда вы изменили метод async для возврата' Task') –

+0

@ Jon Skeet .. Внутри метода PostData я вызываю другой метод, который предназначен для создания restcalls. – vmb

+0

Вы не дожидаетесь своего вызова PostData, поэтому ваш parallel.foreach будет немедленно завершен. Он не будет ждать завершения PostData. – Evk

ответ

0

Проблема в том, что ваш метод PostData выполняется асинхронно, и ничего не говорит параллельный цикл не ждать до завершения все задачи. Альтернативы я хотел бы использовать для синхронизации потока выполнения:

var tasks = items 
.AsParallel() 
.WithDegreeOfParallelisum(...) 
.Select(async item => await PostData(item, id)) 
.ToArray(); 

Task.WaitAll(tasks); // this will wait for all tasks to finnish 

Также ваши методы асинхронных, даже пустота, они должны вернуть Task не пустые. Более четкое описание вашего кода является одним из плюсов этого подхода, кроме того, вы можете использовать эту задачу для любых других операций, например, в случае ожидания.

public async Task PostData<T>(T obj, int id) 

ли вам даже не нужно создавать/запуска задачи асинхронной параллельно, а затем ждать их? Результатом этого является просто создание задач параллельно (что не является тяжелой операцией, поэтому зачем это делать параллельно?). Если вы не делаете никаких дополнительных тяжелых работ в параллельном цикле, кроме метода PostData, я думаю, что вам не нужен параллельный цикл вообще.

+0

Хорошо. Я попробую. Еще одна вещь, я должен указать, что сама PostData вызывает другой метод асинхронизации – vmb

+0

да, это прекрасно,] –

+0

В настоящее время подпись PostMethod недействительна. Могу ли я изменить это? – vmb

3

Почему так бывает?

Потому что вы используете async void.

Кроме того, как упоминал Джон Скит, нет смысла делать параллелизм здесь. Параллельная обработка разбивает работу на несколько потоков. То, что вы действительно хотите параллелизм, не параллелизм, что может быть сделано с Task.WhenAll:

public async Task ItemCheckAsync<T>(IList<T> items, int id) 
{ 
    var tasks = items.Select(current => PostDataAsync(current, id)); 
    await Task.WhenAll(tasks); 
} 
public async Task PostDataAsync<T>(T obj, int id) 

Фраза «параллельно» обычно используется для обозначения «делать больше чем одну вещь за один раз», но это использование вводит вас в заблуждение при использовании Parallel, что в данном случае не является подходящим инструментом. Это одна из причин, почему я сильно предпочитаю термин «одновременный» и резервирую термин «параллельно» для вещей, которые делает класс Parallel.

+0

..Thakas для обмена этой информацией .. – vmb

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