0
    public Task<bool> Submit(TaskScheduler ts, Func<bool> work, object state, TaskContinuationOptions taskContinuationOptions)
    {
        TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>(state, TaskCreationOptions.None);

        Task t1 = new TaskFactory(_cts.Token, TaskCreationOptions.None, taskContinuationOptions, ts).StartNew(() =>
        {
            try
            {
                tcs.SetResult(work());
            }
            catch(Exception e)
            {
                tcs.SetException(e);
            }               
        });

        Task<bool> t2 = tcs.Task;
        t2.ContinueWith(OnTaskSignaled);
        return t2;
    }

    public void OnTaskSignaled(Task<bool> signaledTask) 
    {            
        BusinessItem item = (BusinessItem)signaledTask.AsyncState;
        if (signaledTask.IsCanceled)
        {
            Console.WriteLine("{0} cancelled: Invalid State", item.Id);
        }
        else if (signaledTask.IsFaulted)
        {
            Console.WriteLine("{0} threw: {1}", item.Id, signaledTask.Exception);
        }
        else if (signaledTask.Result == true)
        {
            Console.WriteLine("{0} Succeeded", item.Id);
            // continue to submit
        }
        else if (signaledTask.Result == false)
        {
            Console.WriteLine("{0} Incomplete, retry", item.Id);
            Submit(_ts2, item.Work, item);
        }
    }

上記の例では、taskContinuationOptions オプションは TaskCompletionSource.Task に伝播しますか? デバッグ モードでは、t1 と t2 が 2 つの異なるオブジェクトであることがわかります。実際、state が StartNew(...) に渡された場合、t1 でのみ使用でき、t2 では使用できません。

この場合の TaskFactory は、特定の TaskScheduler ts に作業を送信するためだけに使用されます。別のタスクも作成するという事実は、コードを混乱させます。これを行うための混乱の少ない方法はありますか?タスク プロデューサーである TaskCompletionSource が TaskFactory ほど構成可能でない理由がわかりません。

4

1 に答える 1

2

を使用する理由はありませんTaskCompletionSource。ラムダから値を返す場合、Task返される fromStartNew()には、必要なものが正確に含まれます。成功した場合の結果と失敗した場合の例外です。

TaskContinuationOptionsまた、 inTaskFactoryは、ファクトリを介して直接開始される継続に対してのみ機能すると思います(例: を使用ContinueWhenAll())。そのため、 はまったく必要ないと思いますが、TaskFactory各タスク (オリジナルと継続) ごとにオプションを指定する必要があります。現在のメソッドの外部の誰かが内部継続の実行方法を設定する必要があるのは奇妙だと思いますが。

そして、あなたの質問に答えるために:実際には実行されないためTaskCompletionSource、 someでスケジュールするのは意味がありません。TaskFactoryTaskCompletionSource

これらの変更により、コードは次のようになります。

public Task<bool> Submit(
    TaskScheduler ts, Func<bool> work, object state,
    TaskContinuationOptions taskContinuationOptions)
{
    var task = Task.Factory.StartNew(_ => work(), state, _cts.Token);

    task.ContinueWith(OnTaskSignaled, _cts.Token, taskContinuationOptions,
                      TaskScheduler.Default);

    return task;
}
于 2013-02-14T11:35:39.640 に答える