#c# #multithreading #threadpool #parallel.foreach
#c# #многопоточность #threadpool #parallel.foreach
Вопрос:
В приведенной ниже функции методу всегда передается один и тот же user
объект DoRestCall
(У меня есть регистрация в DoRestCall
методе, и он имеет те же первые данные в user
объекте) Нужно ли мне использовать Parallel.ForEach вместо Threadpool
private void CreateUser(DataServiceCollection<User> epUsers)
{
foreach (User user in epUsers)
{
try
{
ThreadPool.QueueUserWorkItem(new WaitCallback(f =>
{
DoRestCall(string.Format("MESSAGE-TYPE=UserEnrollmentCreateamp;PAYLOAD={0}",
GenarateRequestUserData(user)), true);
}));
}
catch (Exception ex)
{
_logger.Error("Error in CreateUser " ex.Message);
}
}
}
Комментарии:
1. Если вы выполняете вызов REST, зачем использовать
ThreadPool
работу с привязкой к вводу-выводу? Какая версия . Вы используете NET framework2. Я заставляю rest вызывать какие-либо недостатки? C # и .net4.0
3. ДА. Вы выделяете потоки ThreadPool только для того, чтобы блокировать ожидание возврата вызова REST, это пустая трата ресурсов.
4. Есть ли альтернатива для этого?
Ответ №1:
Проблема в том, как обрабатываются переменные цикла при использовании в лямбда-выражении или анонимных методах. Лямбда-выражение видит текущее значение переменной цикла во время выполнения лямбда-выражения. Я считаю, что это поведение было изменено в C # 5.0, но еще не пробовал.
Вам нужно сохранить текущего пользователя в переменной внутри цикла foreach и использовать ее вместо переменной цикла (кроме того, ваш try / catch не улавливает никаких исключений внутри вашего WaitCallback
, см. Исправление Ниже):
foreach (User user in epUsers)
{
User currentUser = user;
ThreadPool.QueueUserWorkItem(new WaitCallback(f =>
{
try
{
DoRestCall(string.Format("MESSAGE-TYPE=UserEnrollmentCreateamp;PAYLOAD={0}",
GenarateRequestUserData(currentUser)), true);
}
catch (Exception ex)
{
_logger.Error("Error in CreateUser " ex.Message);
}
}));
}
Комментарии:
1.
foreach
был изменен в C # 5.0,for
не был, так что вы полностью правы по всем пунктам.