簡體   English   中英

如何使用TaskScheduler安排TaskCompletionSource.Task?

[英]How to schedule a TaskCompletionSource.Task with a TaskScheduler?

    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是兩個不同的對象。 實際上,如果狀態傳遞給StartNew(...),它只能用於t1,但不能用於t2。

在這種情況下,TaskFactory僅用於將工作提交給特定的TaskScheduler,ts。 它還創建了另一個任務的事實使代碼混亂。 是否有一種不那么混亂的方式來做到這一點? 我不明白為什么作為Task生成器的TaskCompletionSource不像TaskFactory那樣可配置。

您沒有理由使用TaskCompletionSource 如果從lambda返回值,則從StartNew()返回的Task將包含您想要的內容:成功的結果和失敗的異常。

此外,我認為TaskFactoryTaskContinuationOptions僅適用於直接通過工廠啟動的延續(例如,使用ContinueWhenAll() )。 因此,我認為您根本不需要TaskFactory ,但是您應該分別為每個任務(原始和繼續)指定選項。 雖然我認為當前方法之外的人應該設置內部延續應該如何執行,這很奇怪。

並回答你的問題:使用一些TaskFactory調度TaskCompletionSource是沒有意義的,因為TaskCompletionSource實際上並沒有執行。

通過這些更改,您的代碼將如下所示:

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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM