Reputation: 122062
I have the following workflow that needs to happen in a non-blocking parallel processing manner. I would like the method DoStuff()
to return immediately so I am using Task Parallel Libary
DoStuff():
Do some setup
Parse an Excel file
then for each row
Fill Template with parsed values
Convert filled template to Pdf
Convert pdf to Tiff
when all row processing has completed Create Summary Text File
when summary text file has completed, Finalize
I'm stumbling a bit with the "when all row processing has been completed" step since I want to return immediately. Is the following roughly what I should be doing?
public Task<ProcessingResult> DoStuff() {
return new Task<SetupResult>(SetUp)
.ContinueWith(ParseExcel, TaskContinuationOptions.OnlyOnRanToCompletion)
.ContinueWith(excelProcessing => {
var templateProcessing = excelProcessing.Result.RowParsing
.Select(template =>
new Task<TemplateFillingResult>(()=>FillTemplate)
.ContinueWith(ConvertToPdf, TaskContinuationOptions.OnlyOnRanToCompletion)
.ContinueWith(ConvertToTiff, TaskContinuationOptions.OnlyOnRanToCompletion)
).ToArray()
//-------------------------------------------------------------
// This is the part that seems wierd
//-------------------------------------------------------------
Task.Factory.ContinueWhenAll(templateTasks, t=> { }).Wait();
return new TemplatesProcessingResult(templateProcessing);
}, TaskContinuationOptions.OnlyOnRanToCompletion)
.ContinueWith(CreateSummaryFile, TaskContinuationOptions.OnlyOnRanToCompletion)
.ContinueWith(FinalizeProcessing, TaskContinuationOptions.OnlyOnRanToCompletion);
Upvotes: 2
Views: 608
Reputation: 41236
I think you're getting confused because you are trying to wire up all those components as continuations of the original event. If there is no compelling reason to make all of those calls continuations, then this can all be simply done with a single background thread (task).
var task = Task.Factory.StartNew(() =>
{
// setup
// var stuff = ParseFile()
// Executes elements in parallel and blocks this thread until all have completed, else bubbles the exception up
var transformations = excelProcessing.Result.RowParsing.AsParallel().Select(x =>
{
FillTemplate(x);
}).ToArray();
// create summary text file
// Finalize
return processingResult;
});
Basically, you can do all of that in a single thread and not have to worry about it. Marking up all those steps as continuations is pretty convoluted for what you need to do.
Then your calling code can simply block on the Result
property of that guy to get the result of the asynchronous call:
try
{
var result = task.Result;
}
catch(AggregateException e)
{
e.Flatten().Handle(ex =>
{
// Do Stuff, return true to indicate handled
});
}
However, the one thing you will need to be cognizant of is exceptions. If this is going to be a fire and forget task, then if you have an exception, it's going to bubble all the way up and potentially kill your process.
Upvotes: 6