ThreadPool.QueueUserWorkItem внутри 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=UserEnrollmentCreate&PAYLOAD={0}",
                                         GenarateRequestUserData(user)), true);
            }));
        }
        catch (Exception ex)
        {
            _logger.Error("Error in CreateUser " + ex.Message);
        }
    }
}

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=UserEnrollmentCreate&PAYLOAD={0}",
                                     GenarateRequestUserData(currentUser)), true);
        }
        catch (Exception ex)
        {
            _logger.Error("Error in CreateUser " + ex.Message);
        }
    }));
}
Другие вопросы по тегам