【问题标题】:ThreadPool.QueueUserWorkItem inside foreach use same datasetforeach 中的 ThreadPool.QueueUserWorkItem 使用相同的数据集
【发布时间】:2014-06-24 06:19:43
【问题描述】:

在下面的函数中,总是将相同的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);
        }
    }
}

【问题讨论】:

  • 如果您正在进行 REST 调用,为什么要使用 ThreadPool 进行 I/O 绑定工作?您使用的是哪个版本的 .NET 框架
  • 是的,我正在休息打电话有什么缺点吗? C# 和 .net4.0
  • 是的。你分配一个ThreadPool线程只是为了阻塞等待REST调用返回,很浪费资源。
  • 有什么替代品吗?

标签: c# multithreading threadpool parallel.foreach


【解决方案1】:

问题是在 lambda 表达式或匿名方法中使用循环变量时如何处理。 lambda 表达式在执行 lambda 时查看循环变量的当前值。我相信这种行为在 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);
        }
    }));
}

【讨论】:

  • foreach 在 C# 5.0 中已更改,for 未更改,因此您完全正确。
猜你喜欢
  • 1970-01-01
  • 2014-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-01
  • 2013-01-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多