web-dev-qa-db-ja.com

Task.Factory.StartNewを使用してメソッドパラメーターを渡す

私は次のコードを持っています:

var task = Task.Factory.StartNew(CheckFiles, cancelCheckFile.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);

private void CheckFiles()
{
  //Do stuff
}

CheckFilesを修正して、整数とBlockingCollection参照を受け入れたい

private void CheckFiles(int InputID, BlockingCollection<string> BlockingDataCollection)
{
  //Do stuff
}

上記のように、このタスクを開始する方法を見つけることができないようです。

手伝ってくれますか?

ありがとう

58
Jon

最適なオプションは、表示する変数を閉じるラムダ式を使用することです。

ただし、この場合、特にループでこれを呼び出す場合は注意してください。 (変数は「ID」であるため、これに言及します。これはこの状況では一般的です。)間違ったスコープで変数を閉じると、バグが発生する可能性があります。詳細については、 Eric Lippertのこの件に関する投稿 を参照してください。通常、これには一時的なものが必要です。

foreach(int id in myIdsToCheck)
{
    int tempId = id; // Make a temporary here!
    Task.Factory.StartNew( () => CheckFiles(tempId, theBlockingCollection),
         cancelCheckFile.Token, 
         TaskCreationOptions.LongRunning, 
         TaskScheduler.Default);
}

また、コードが上記のような場合、LongRunningヒントの使用に注意する必要があります。デフォルトのスケジューラーを使用すると、ThreadPoolを使用する代わりに各タスクが独自の専用スレッドを取得します。多くのタスクを作成している場合、ThreadPoolの利点が得られないため、これは悪影響を与える可能性があります。通常、単一の長時間実行されるタスク(その名前)を対象としており、コレクションのアイテムなどで機能するように実装されるものではありません。

99
Reed Copsey
class Program
{
    static void Main(string[] args)
    {
        Task.Factory.StartNew(() => MyMethod("param value"));
    }

    private static void MyMethod(string p)
    {
        Console.WriteLine(p);
    }
}
19

単一の整数を渡すために、Reed Copseyの答えに同意します。将来、より複雑な構造体を渡す場合は、個人的にすべての変数を匿名型として渡したいと考えています。次のようになります。

foreach(int id in myIdsToCheck)
{
    Task.Factory.StartNew( (Object obj) => 
        {
           var data = (dynamic)obj;
           CheckFiles(data.id, theBlockingCollection,
               cancelCheckFile.Token, 
               TaskCreationOptions.LongRunning, 
               TaskScheduler.Default);
        }, new { id = id }); // Parameter value
}

詳細については、私の blog をご覧ください。

6
paulselles

Action のインスタンスとして最初のパラメーターを構築します。

var inputID = 123;
var col = new BlockingDataCollection();
var task = Task.Factory.StartNew(
    () => CheckFiles(inputID, col),
    cancelCheckFile.Token,
    TaskCreationOptions.LongRunning,
    TaskScheduler.Default);
5
Adam Ralph