C# Могу ли я передать более одного данных в мой целевой метод при использовании ThreadPool?

Использование ThreadPool.QueueUserWorkItem (WaitCallback, Object) начать поток с моим целевым методом и данными. Могу ли я передать в метод несколько данных? второй параметр в QueueUserWorkItem (WaitCallback, Object) может быть массив?

7 ответов

Решение

Вот пример использования класса, чтобы вы могли получить строго типизированные праматеры

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
}

Второй параметр может быть массивом, но вам лучше создать собственный класс для хранения ваших данных. Таким образом, данные, которые вы передаете, полностью напечатаны.

Да, тип аргумента - System.Object, поэтому вы можете передать что угодно. http://msdn.microsoft.com/en-us/library/4yd16hza.aspx

Просто приведите ваш объект состояния обратно, что также относится к ParameterizedThreadStart:

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

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

Наиболее удобный способ - использовать лямбда-выражение:

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

Это самый разумный способ использовать этот API.

Компилятор C# сгенерирует класс внутри. Этот метод (виртуально) так же быстр, как явно использует класс.

Все типы в.NET являются производными от объекта, поэтому вы можете передать в QueueUserWorkItem все, что захотите. Просто приведите его в свой метод WaitCallback.

Использование лямбда-выражения - действительно самый простой способ.

Однако не использовать аргумент состояния ThreadPool.QueueUserWorkItem для передачи аргументов следует рассматривать как анти-шаблон:

Следующее последовательно работает в моем приложении:

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)

Другие вопросы по тегам