TaskCompletionSource<TResult> クラス

定義

デリゲートにバインドされていない Task<TResult> のプロデューサー側を表し、Task プロパティを介してコンシューマー側にアクセスできるようにします。

generic <typename TResult>
public ref class TaskCompletionSource
public class TaskCompletionSource<TResult>
type TaskCompletionSource<'Result> = class
Public Class TaskCompletionSource(Of TResult)

型パラメーター

TResult

この TaskCompletionSource<TResult>に関連付けられている結果値の型。

継承
TaskCompletionSource<TResult>

次の例は、TaskCompletionSource<TResult>の使用方法を示しています。

using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

class TCSDemo
{
    // Demonstrated features:
    // 		TaskCompletionSource ctor()
    // 		TaskCompletionSource.SetResult()
    // 		TaskCompletionSource.SetException()
    //		Task.Result
    // Expected results:
    // 		The attempt to get t1.Result blocks for ~1000ms until tcs1 gets signaled. 15 is printed out.
    // 		The attempt to get t2.Result blocks for ~1000ms until tcs2 gets signaled. An exception is printed out.
    static void Main()
    {
        TaskCompletionSource<int> tcs1 = new TaskCompletionSource<int>();
        Task<int> t1 = tcs1.Task;

        // Start a background task that will complete tcs1.Task
        Task.Factory.StartNew(() =>
        {
            Thread.Sleep(1000);
            tcs1.SetResult(15);
        });

        // The attempt to get the result of t1 blocks the current thread until the completion source gets signaled.
        // It should be a wait of ~1000 ms.
        Stopwatch sw = Stopwatch.StartNew();
        int result = t1.Result;
        sw.Stop();

        Console.WriteLine("(ElapsedTime={0}): t1.Result={1} (expected 15) ", sw.ElapsedMilliseconds, result);

        // ------------------------------------------------------------------

        // Alternatively, an exception can be manually set on a TaskCompletionSource.Task
        TaskCompletionSource<int> tcs2 = new TaskCompletionSource<int>();
        Task<int> t2 = tcs2.Task;

        // Start a background Task that will complete tcs2.Task with an exception
        Task.Factory.StartNew(() =>
        {
            Thread.Sleep(1000);
            tcs2.SetException(new InvalidOperationException("SIMULATED EXCEPTION"));
        });

        // The attempt to get the result of t2 blocks the current thread until the completion source gets signaled with either a result or an exception.
        // In either case it should be a wait of ~1000 ms.
        sw = Stopwatch.StartNew();
        try
        {
            result = t2.Result;

            Console.WriteLine("t2.Result succeeded. THIS WAS NOT EXPECTED.");
        }
        catch (AggregateException e)
        {
            Console.Write("(ElapsedTime={0}): ", sw.ElapsedMilliseconds);
            Console.WriteLine("The following exceptions have been thrown by t2.Result: (THIS WAS EXPECTED)");
            for (int j = 0; j < e.InnerExceptions.Count; j++)
            {
                Console.WriteLine("\n-------------------------------------------------\n{0}", e.InnerExceptions[j].ToString());
            }
        }
    }
}
Imports System.Diagnostics
Imports System.Threading
Imports System.Threading.Tasks

Module TCSDemo
    ' Demonstrated features:
    '   TaskCompletionSource ctor()
    '   TaskCompletionSource.SetResult()
    '   TaskCompletionSource.SetException()
    '   Task.Result
    ' Expected results:
    '   The attempt to get t1.Result blocks for ~1000ms until tcs1 gets signaled. 15 is printed out.
    '   The attempt to get t2.Result blocks for ~1000ms until tcs2 gets signaled. An exception is printed out.

    Private Sub Main()
        Dim tcs1 As New TaskCompletionSource(Of Integer)()
        Dim t1 As Task(Of Integer) = tcs1.Task

        ' Start a background task that will complete tcs1.Task
        Task.Factory.StartNew(Sub()
                                  Thread.Sleep(1000)
                                  tcs1.SetResult(15)
                              End Sub)

        ' The attempt to get the result of t1 blocks the current thread until the completion source gets signaled.
        ' It should be a wait of ~1000 ms.
        Dim sw As Stopwatch = Stopwatch.StartNew()
        Dim result As Integer = t1.Result
        sw.Stop()

        Console.WriteLine("(ElapsedTime={0}): t1.Result={1} (expected 15) ", sw.ElapsedMilliseconds, result)

        ' ------------------------------------------------------------------

        ' Alternatively, an exception can be manually set on a TaskCompletionSource.Task
        Dim tcs2 As New TaskCompletionSource(Of Integer)()
        Dim t2 As Task(Of Integer) = tcs2.Task

        ' Start a background Task that will complete tcs2.Task with an exception
        Task.Factory.StartNew(Sub()
                                  Thread.Sleep(1000)
                                  tcs2.SetException(New InvalidOperationException("SIMULATED EXCEPTION"))
                              End Sub)

        ' The attempt to get the result of t2 blocks the current thread until the completion source gets signaled with either a result or an exception.
        ' In either case it should be a wait of ~1000 ms.
        sw = Stopwatch.StartNew()
        Try
            result = t2.Result

            Console.WriteLine("t2.Result succeeded. THIS WAS NOT EXPECTED.")
        Catch e As AggregateException
            Console.Write("(ElapsedTime={0}): ", sw.ElapsedMilliseconds)
            Console.WriteLine("The following exceptions have been thrown by t2.Result: (THIS WAS EXPECTED)")
            For j As Integer = 0 To e.InnerExceptions.Count - 1
                Console.WriteLine(vbLf & "-------------------------------------------------" & vbLf & "{0}", e.InnerExceptions(j).ToString())
            Next
        End Try
    End Sub

End Module

注釈

多くのシナリオでは、外部の非同期操作を表す Task<TResult> を有効にすると便利です。 TaskCompletionSource<TResult> は、この目的のために提供されています。 これにより、コンシューマーに渡すことができるタスクを作成できます。 コンシューマーは、タスク メンバー変数を処理する他のシナリオと同じように、タスクのメンバーを使用できます。 ただし、ほとんどのタスクとは異なり、TaskCompletionSource によって作成されたタスクの状態は、TaskCompletionSource のメソッドによって明示的に制御されます。 これにより、外部非同期操作の完了を基になるタスクに伝達できます。 また、この分離により、コンシューマーは対応する TaskCompletionSource にアクセスせずに状態を遷移できなくなります。 詳細については、「.NET を使用した並列プログラミング」ブログ 「TaskCompletionSource<TResult> の性質」のエントリを参照してください。

並列拡張のサンプル には、TaskCompletionSource<TResult>の使用方法の例も含まれています。

コンストラクター

TaskCompletionSource<TResult>()

TaskCompletionSource<TResult>を作成します。

TaskCompletionSource<TResult>(Object)

指定した状態の TaskCompletionSource<TResult> を作成します。

TaskCompletionSource<TResult>(Object, TaskCreationOptions)

指定した状態とオプションを使用して TaskCompletionSource<TResult> を作成します。

TaskCompletionSource<TResult>(TaskCreationOptions)

指定したオプションを使用して TaskCompletionSource<TResult> を作成します。

プロパティ

Task

この TaskCompletionSource<TResult>によって作成された Task<TResult> を取得します。

メソッド

Equals(Object)

指定したオブジェクトが現在のオブジェクトと等しいかどうかを判断します。

(継承元 Object)
GetHashCode()

既定のハッシュ関数として機能します。

(継承元 Object)
GetType()

現在のインスタンスの Type を取得します。

(継承元 Object)
MemberwiseClone()

現在の Objectの簡易コピーを作成します。

(継承元 Object)
SetCanceled()

基になる Task<TResult>Canceled 状態に遷移します。

SetCanceled(CancellationToken)

指定したトークンを使用して、基になる Task<TResult>Canceled 状態に遷移します。

SetException(Exception)

基になる Task<TResult>Faulted 状態に遷移し、指定した例外にバインドします。

SetException(IEnumerable<Exception>)

基になる Task<TResult>Faulted 状態に移行し、例外オブジェクトのコレクションをバインドします。

SetFromTask(Task<TResult>)

基になる Task<TResult> を、指定した completedTaskと同じ完了状態に遷移します。

SetResult(TResult)

基になる Task<TResult>RanToCompletion 状態に遷移します。

ToString()

現在のオブジェクトを表す文字列を返します。

(継承元 Object)
TrySetCanceled()

基になる Task<TResult>Canceled 状態に移行しようとします。

TrySetCanceled(CancellationToken)

基になる Task<TResult>Canceled 状態に移行しようと試み、取り消されたタスクにキャンセル トークンを格納できるようにします。

TrySetException(Exception)

基になる Task<TResult>Faulted 状態に移行し、指定した例外にバインドしようとします。

TrySetException(IEnumerable<Exception>)

基になる Task<TResult>Faulted 状態に移行し、例外オブジェクトのコレクションをバインドしようとします。

TrySetFromTask(Task<TResult>)

基になる Task<TResult> を、指定した completedTaskと同じ完了状態に遷移しようとします。

TrySetResult(TResult)

基になる Task<TResult>RanToCompletion 状態に移行しようとします。

適用対象

スレッド セーフ

TaskCompletionSource<TResult> のすべてのメンバーはスレッド セーフであり、複数のスレッドから同時に使用できます。

こちらもご覧ください

  • TPL を他の非同期パターンと共に使用する
  • 方法: タスク で EAP パターンをラップする