ThreadPool.QueueUserWorkItem (WaitCallback, Object)
ターゲットメソッドとデータでスレッドを開始するために使用します。メソッドに複数のデータを渡すことはできますか? の 2 番目のパラメーターはQueueUserWorkItem (WaitCallback, Object)
配列にすることができますか?
7 に答える
2番目のパラメーターは配列にすることができますが、データを含めるためのカスタムクラスを作成することをお勧めします。このようにして、渡すデータは完全に入力されます。
状態オブジェクトをキャストバックするだけです。これはParameterizedThreadStartにも適用されます。
List<string> list = new List<string> {"1","2","3"};
ThreadPool.QueueUserWorkItem (CallBack, list);
void CallBack(object state)
{
List<string> list = (List<string>) state;
}
強く型付けされたプラマーターを取得できるように、クラスを使用する例を次に示します。
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
最も便利な方法は、ラムダ式を使用することです。
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 でテスト済み)