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)