2012-11-03 82 views
3

我一直在尋找在CodePlex上下載管理器類型的項目,來到翻過這一個: http://nthdownload.codeplex.com/消費的同步或異步方法作爲任務

瀏覽我碰到的方法似的跑AddDownloads的代碼,如下所示:

AddDownloads啓動_downloadQueue.AddDownloads任務並繼續執行viewMaintenanceTask任務。如果你看看在這兩個任務和下游發生的方法和事情,似乎一切都是同步的。

也讀這篇博文,Synchronous tasks with Task我想了解的優勢,如果有的話,在TaskCompletionSource包裝同步方法。是因爲它爲API消費者提供了在單獨的線程上啓動任務的選項,或者僅僅是因爲您想要使用該方法作爲Task。包裝在TaskCompletionSource中的同步方法是否受益於並行處理?

private Task<QueueOperation> AddDownloads(IEnumerable<IDownload> downloads, out Task<QueueOperation> startTask) 
{ 
    var addTask = _downloadQueue.AddDownloads(downloads, out startTask); 

    // Maintain views 
    var viewMaintenanceTask = addTask.ContinueWith(t => 
    { 
     if (t.Exception == null) 
     { 
      var addedDownloads = t.Result.DownloadErrors.Where(k => k.Value == null).Select(k => k.Key).ToList(); 
      var activeDownloads = ActiveDownloads.ToList(); 
      AddToActiveDownloads(addedDownloads.Except(activeDownloads).ToList(), false); 
     } 
     else 
     { 
      // Rethrow exception, this ensures it'll bubble up to any further ContinueWith chained off this task 
      throw t.Exception; 
     } 
     return t.Result; 
    }); 

    return viewMaintenanceTask; 
} 

從博客文章的示例方法中,在包裝TaskCompletionSource一個同步操作:

var tcs = new TaskCompletionSource<object>(); 

try 
{ 
    object result = model.Deserialize(stream, null, type); 
    tcs.SetResult(result); 
} 
catch (Exception ex) 
{ 
    tcs.SetException(ex); 
} 

return tcs.Task; 

回答

9

是否包裹在從TaskCompletionSource益處和並行處理的同步方法?

號創建TaskCompletionSource以任何方式,形狀或形式創建一個新的線程。

您在底部給出的代碼非常毫無意義 - 當方法返回時,任務已經完成(或故障)。如果你不得不消耗一項任務,它只會只有有任何用處。我可能將其更改爲:

try 
{ 
    return Task.FromResult(model.Deserialize(stream, null, type)); 
} 
catch (Exception ex) 
{ 
    // There's no Task.FromException, unfortunately. 
    var tcs = new TaskCompletionSource<object>(); 
    tcs.SetException(ex); 
    return tcs.Task; 
} 

在C#這是寫一個async方法沒有await表達等價的:

public static async Task<object> Deserialize(Model model, Stream stream, 
              Type type) 
{ 
    return model.Deserialize(stream, null, type); 
} 

如果你想真正的並行性,你應該使用Task.Run(.NET 4.5)或者Task.Factory.StartNew(.NET 4)。

+0

所以,在這些例子中,沒有任何理由在TCS中包裝代碼。 –

+0

是否正在等待包含在TCS中的同步代碼與通常調用方法時調用它的內容相同? –

+0

@DerekBeattie:如果TCS已經完成,它們大部分是等價的。有一些微妙的差異,但我懷疑它們適用於此。 –