2012-05-02 6 views
32

TaskCompletionSourceの目的と非同期/スレッドレス作業の関係を理解し​​ようとしています。私は一般的な考えがあると思うが、私の理解が正しいことを確認したい。TaskCompletionSource - スレッドレス非同期作業を理解しようとしています

まず、自分のスレッドレス/非同期作業を作成するための良い方法があるかどうかを調べるために、タスク並列ライブラリ(TPL)を調べ始めました(ASP.NETサイトのスケーラビリティを向上させようとしています) TPLの理解は将来的に非常に重要になるように見える(async/await)。これは私をTaskCompletionSourceに導いた。

私の理解では、あなたのクラスの1つにTaskCompletionSourceを追加することは、あなたのコーディングの非同期化を行う際にはあまり効果がありません。まだ同期コードを実行している場合は、コードへの呼び出しがブロックされます。私はこれがマイクロソフトのAPIにも当てはまると思う。たとえば、WebClientクラスのDownloadStringTaskAsyncで、最初に行っていたセットアップ/同期コードはブロックされます。あなたが実行しているコードは、現在のスレッドか、新しいスレッドをスピンオフする必要がありますいくつかのスレッドで実行する必要があります。

asyncをMicrosoftから呼び出して呼び出すときに、自分のコードにTaskCompletionSourceを使用すると、クラスのクライアントはクラスをブロックしないように新しいスレッドを作成する必要はありません。

Microsoftが非同期APIを内部的にどのように行うのかよくわかりません。たとえば、.Net 4.5のSqlDataReaderの新しいasyncメソッドがあります。私はIO完了ポートがあることを知っています。おそらくほとんどのC#開発者が使用しない抽象レベル(C++?)は低いレベルだと思います。 IO完了ポートがデータベースまたはネットワークコール(HTTP)に対して機能するかどうか、またはファイルIOに使用されているかどうかはわかりません。

質問は正しいですか?私が間違って表現したことはありますか?

+0

:私たちは、エラーや過度のリソース消費せずに一度 でこれらの操作の万を開始することでこれを実証することができます ? –

+0

私の理解が正しければ...確かではないかどうかわからない – coding4fun

答えて

53

TaskCompletionSourceは、コードを実行しないオブジェクトTaskの作成に使用されます。

これらは、I/Oベースの非同期操作(または非CPUベースの非同期操作、タイムアウトなど)があるときは、Microsoftの新しい非同期APIによってかなり使用されています。また、あなたが書くasync Taskメソッドは、返されたTaskを完了するためにTCSを使用します。

Taskインスタンスを作成するさまざまな方法については、ブログの投稿Creating Tasksがあります。これは、async/awaitの視点(TPLの視点ではない)から書かれていますが、ここでも適用されます。

またスティーブンToubの優れた記事を参照してください。

+0

スティーブンがありがとうございますが、内部についての私の理解は正しいですか? – coding4fun

+1

非同期メソッドは、(もちろん)非同期操作を開始するために使用される同期部分を持ちます。 IIRCでは、IOCPはあらゆる種類の 'HANDLE'ベースのデータ転送に使用することができ、それをラップする' async'メソッドで 'Begin' /' End'ラップでIOCP操作をラップすることは珍しくありません(今日) 'TaskCompletionSource'を使って)' Task'で実行します。 –

+0

私はTaskCompletionSourceの使い方を理解しようとしていますが、なぜコードを実行しないタスクがあるのか​​混乱しています。私はあなたのブログ記事を読む。呼び出し元が購読できるイベントとしてTCSが使用されているようですが、通常のタスクを使用してタスクが完了するまで待つときに、なぜそれをしたいのですか? –

4

私は

第2段落では、我々が見てきた

下回っている(申し訳ありませんが、リンクは、現時点では死んでもよい)

http://tutorials.csharp-online.net/TaskCompletionSourceで提供された説明が好きTask.Runは、 プールされた(またはプールされていない)スレッドでデリゲートを実行するタスクを作成する方法を説明します。タスクを作成する別の方法は、 TaskCompletionSourceです。

TaskCompletionSourceを使用すると、後で が開始して終了する操作からタスクを作成できます。これは、手動で駆動する「スレーブ」の タスクを実行することによって動作します。これは、操作がいつ終了するかを、 または障害で示します。 操作の間、スレッドをブロックすることなく、戻り値、例外、 および継続を伝播する能力のすべての利点を得ることがI/O関連の作業に最適です。

TaskCompletionSourceを使用するには、クラスをインスタンス化するだけです。 は、他のタスクと同様に、 を待ち、継続をアタッチできるタスクを返すTaskプロパティを公開します。タスクは、 しかし、 介しTaskCompletionSourceオブジェクトによって完全に制御されて、次の方法:これらの方法のいずれかを呼び出す

public class TaskCompletionSource<TResult> 
{ 
public void SetResult(TResult result); 
public void SetException (Exception exception); 

public void SetCanceled(); 
public bool TrySetResult (TResult result); 
public bool TrySetException (Exception exception); 
public bool TrySetCanceled(); 
... 
} 

は故障、またはキャンセル、完了 にそれを入れ、タスクを知らせます状態(後者は セクションの「キャンセル」セクションに記載されています)。これらのメソッドのうちの1つをと呼びます:再度呼び出された場合、SetResult、SetException、またはSetCanceled は例外をスローしますが、Try *メソッドはfalseを返します。

次の例では、5秒間待って42を出力します。TaskCompletionSourceの本当の力が がスレッドをタイアップしていないタスクを作成している

var tcs = new TaskCompletionSource<int>(); 
new Thread (() =>  { 
         Thread.Sleep (5000); 
         tcs.SetResult (42); 
         })  
      .Start(); 
Task<int> task = tcs.Task; // Our "slave" task. 
Console.WriteLine(task.Result); // 42 

その他の興味深い引用符

..以降

上糸なしTaskCompletionSourceの私達の使用は継続が起動したときにのみ、スレッド は5秒後に、従事していることを意味しています。質問はここで何

+0

リンクが無効です。 –

+1

素敵な説明 – Ricky

関連する問題