9

.NET 4.0 で TPL を使用して新しい副作用のみのタスク (つまり、結果を返さないタスク) を開始するための奇抜な方法は、次の API を使用することです。

Task Task.Factory.StartNew(Action<object>, object)   

しかし、なぜこの API の署名はこのように見えないのですか?

Task Task.Factory.StartNew<T>(Action<T>, T) 

またはこのように

Task Task.Factory.StartNew<T>(T, Action<T>) 

技術的な理由ですか、それとも他の理由ですか?

4

2 に答える 2

7

さて、私は質問を正しく理解したので:)

これは、 の直接の代替ThreadPool.QueueUserWorkItemとなることが意図されているためだと思います。少し奇妙に思えることに同意します...しかし、とにかくラムダ式を使用している場合、状態パラメーターを受け取るバージョンを使用する方がおそらく簡単です(つまりAction、の代わりにAction<object>)、興味のある値を事前にキャプチャするだけです. 値と関数を別々に指定している場合は役に立ちません:(

于 2009-12-03T14:13:21.060 に答える
3

Stephen Toub (MSFT) の投稿によると、彼らは、状態データを渡すためにクロージャーに依存しようとしていると想定しています。署名のあいまいさについての言い訳もありました。( http://social.msdn.microsoft.com/Forums/en/parallelextensions/thread/1988294c-de41-476a-a104-aa550b7409f5 )

ただし、この問題を解決するためにクロージャーに依存することは、より良い解決策を待っている一時的なハックのように思えます。それは機能しますが、長期的な解決策としては適切ではありません。単純にアクションとしてデリゲート メソッドを指定するのが最も簡単な方法であることがよくありますが、それは、グローバル変数を使用する必要があるか、状態パラメーターの受け渡しから除外されることを意味します。

Hugo の提案の 1 つが気に入っています (MS フォーラムの投稿から)。Hugo は、TaskState 型を導入することを提案しました。これは、ジェネリックのあいまいさの問題を回避する賢い方法のようです。

これを Task.Factory.StartNew() シグネチャと Task() コンストラクターに適用すると、次のようになります。

  public Task<T>( Action<T> function, TaskState<T> state );
  public Task<T,TResult>( Func<T,TResult> function, TaskState<T> state );

ActionState は、Nullable クラスによく似ています。つまり、Value メンバーの単純なラッパーです。実際には、TaskState の使用は次のようになります。

  var myTask = new Task( MyMethod, new TaskState( stateInfo ) );
  ...

  public void MyMethod( StateInfo stateInfo ) { ... }

TaskState<> ソリューションは完全ではありませんが、型キャストのクロージャーに依存するよりもはるかに優れたソリューションのようです。

于 2011-03-11T21:44:47.930 に答える