【问题标题】:C# Can I pass more than one data into my target method when using ThreadPool?C# 使用 ThreadPool 时,我可以将多个数据传递到我的目标方法吗?
【发布时间】:2011-01-18 19:48:53
【问题描述】:

使用ThreadPool.QueueUserWorkItem (WaitCallback, Object) 用我的目标方法和数据启动一个线程。我可以将多个数据传递到我的方法中吗? QueueUserWorkItem (WaitCallback, Object)中的第二个参数可以是数组吗?

【问题讨论】:

    标签: c# multithreading threadpool queueuserworkitem


    【解决方案1】:

    第二个参数可以是一个数组,但您最好创建一个自定义类来包含您的数据。这样你传递的数据就是完全类型化的。

    【讨论】:

      【解决方案2】:

      这是一个使用类的示例,因此您可以获得强类型的 pramaters

      public class CreateUserTaskInfo
      {
          public string username { get; };
          public string password { get; };
          public string sqlServer { get; };
          public string database { get; };
          public string practice { get; };
          public RemoteUserManager client { get; };
          public CreateUserTaskInfo(RemoteUserManager cli, string usr, string pass, string sql, string db, string prac)
          {
              client = cli;
              username = usr;
              password = pass;
              sqlServer = sql;
              database = db;
              practice = prac;
          }
      }
      
      public void ExampleFunction(...)
      {
          //gather up the variables to be passed in
          var taskInfo = new CreateUserTaskInfo(remote, user, password, SqlInstancePath, AccountID, practiceName);
      
          //queue the background work and pass in the state object.
          ThreadPool.QueueUserWorkItem(new WaitCallback(RemoteUserManagerClient.CreateUser), taskInfo);
      }
      
      static public void CreateUser(object stateInfo)
      {
          CreateUserTaskInfo ti = (CreateUserTaskInfo)stateInfo;
      
          //use ti in the method and access the properties, it will be 
          // the same object as taskInfo from the other method
      }
      

      【讨论】:

        【解决方案3】:

        是的,参数的类型是 System.Object,所以你可以传递任何东西。 http://msdn.microsoft.com/en-us/library/4yd16hza.aspx

        【讨论】:

          【解决方案4】:

          只需将您的状态对象转换回,这也适用于ParameterizedThreadStart

          List<string> list = new List<string> {"1","2","3"};
          ThreadPool.QueueUserWorkItem (CallBack, list);
          
          void CallBack(object state)
          {
              List<string> list = (List<string>) state;
          }
          

          【讨论】:

            【解决方案5】:

            .NET 中的所有类型都派生自对象,因此您可以将任何您想要的内容传递给 QueueUserWorkItem。只需将其转换为您的 WaitCallback 方法即可。

            【讨论】:

              【解决方案6】:

              最方便的方法是使用 lambda 表达式:

              var localVariable = 42;
              ThreadPool.QueueUserWorkItem (_ => { Console.WriteLine(localVariable); }, null);
              

              这是使用此 API 的最明智的方式。

              C# 编译器将在内部生成一个类。此方法(实际上)与显式使用类一样快。

              【讨论】:

                【解决方案7】:

                使用 lambda 表达式确实是最简单的方法。

                但是,不使用 ThreadPool.QueueUserWorkItem 的 state 参数来传递参数应该被视为一种反模式:

                以下内容在我的应用中始终有效:

                var parm = new ParallelInput()
                                        {
                                            threadIdNbr = threadId,
                                            input = input,
                                            inputLength = inputLen,
                                            leftBlock = leftBlock,
                                            leftBlockLength = leftBlockLength,
                                            leftSiblingThreadData = leftSiblingThreadData,
                                            rightSiblingThreadData = rightSiblingThreadData, 
                                            threadCommon = threadCommon,
                                            globalOutputWriter = globalOutputWriter,
                                            threadWrittenAllCounter = threadWrittenAllCounter
                                        };
                
                ThreadPool.QueueUserWorkItem(pp => { var p = (ParallelInput)pp; rdr.parallelConvert(p.threadIdNbr, p.input, p.inputLength, p.leftBlock, p.leftBlockLength, p.leftSiblingThreadData, p.rightSiblingThreadData, p.threadCommon, p.globalOutputWriter, p.threadWrittenAllCounter); }, parm);
                

                ...并且以下在我的硬件上始终失败:

                ThreadPool.QueueUserWorkItem(_ => rdr.parallelConvert(threadId, input, inputLen, leftBlock, leftBlockLength, leftSiblingThreadData, rightSiblingThreadData, threadCommon, globalOutputWriter, threadWrittenAllCounter), null);
                

                ... 因为它无法提供输入数组中的所有数据。 (使用 VS2010 和 .NET v4.0.30319 测试)

                【讨论】:

                  猜你喜欢
                  • 2020-02-12
                  • 2015-12-29
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-10-13
                  • 1970-01-01
                  相关资源
                  最近更新 更多