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

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

Ответы [ 7 ]

4 голосов
/ 19 февраля 2010

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

3 голосов
/ 19 февраля 2010

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

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 голосов
/ 19 февраля 2010

Просто приведите ваш объект состояния обратно, что также относится к 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 голосов
/ 19 февраля 2010

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

1 голос
/ 27 января 2012

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

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

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

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

1 голос
/ 19 февраля 2010

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

0 голосов
/ 28 июня 2016

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

Однако не использовать аргумент состояния 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)

...