Reputation: 9478
I was looking at download manager type project on codeplex and came accross this one: http://nthdownload.codeplex.com/
Browsing the code I ran across methods like AddDownloads
, listed below:
AddDownloads
starts the _downloadQueue.AddDownloads Task and continues with the viewMaintenanceTask
Task. If you look at the methods and things that happen in those 2 tasks and downstream it seems like everything is synchronous.
Also reading this blog post, Synchronous tasks with Task I'm trying to understand the advantage, if any, to wrapping synchronous methods in a TaskCompletionSource
. Is it because it gives the API consumer the option to start the task on a separate thread or simply because you want to consume the method as a Task
. Does a synchronous method wrapped in a TaskCompletionSource
benefit from and parallel processing?
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;
}
The example method from the blog post, wrapping a synchronous operation in a 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;
Upvotes: 3
Views: 1366
Reputation: 1503489
Does a synchronous method wrapped in a TaskCompletionSource benefit from and parallel processing?
No. Creating a TaskCompletionSource
does not create a new thread in any way, shape or form.
The code you've given at the bottom is pretty pointless - the task will already be completed (or faulted) when the method returns. It would only be any use if you had to consume a task. I'd probably change it to:
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;
}
In C# it's the equivalent of writing an async
method without an await
expression:
public static async Task<object> Deserialize(Model model, Stream stream,
Type type)
{
return model.Deserialize(stream, null, type);
}
If you want genuine parallelism, you should use Task.Run
(.NET 4.5) or Task.Factory.StartNew
(.NET 4).
Upvotes: 9