C#使用ThreadPool时,我可以将多个数据传递给我的目标方法吗?

时间:2010-02-19 14:59:45

标签: c# multithreading threadpool queueuserworkitem

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

7 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:3)

是参数的类型是System.Object,因此您可以传递任何内容。 http://msdn.microsoft.com/en-us/library/4yd16hza.aspx

答案 2 :(得分:3)

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

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

void CallBack(object state)
{
    List<string> list = (List<string>) state;
}

答案 3 :(得分:3)

以下是使用类的示例,以便您可以获得强类型的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
}

答案 4 :(得分:1)

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

答案 5 :(得分:1)

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

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

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

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

答案 6 :(得分:0)

使用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测试)