Reputation: 533
I am trying to run 3 of tasks on different threads (there will be a few more added.) The tasks that are called then call other tasks that are async / await.
The program execution continues after my command to wait. Execution needs to wait until all tasks are complete. My code is below (the null return is just there to test, I still need to create the return code.
public List<string> CopyFilesAsync(List<ModelIterationModel> model)
{
var copyFileTaskParameters = GetCopyFileTaskParameters(model);
Task<List<CopyFitDataResult>> fitDataResulLits = null;
Task<List<CopyNMStoreResult>> nmStoreResultsList = null;
Task<List<CopyDecompAnalyzerResult>> decompAnalyzerStoreResultsList = null;
Task parent = Task.Factory.StartNew(() =>
{
var cancellationToken = new CancellationToken();
TaskFactory factory = new TaskFactory(TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously);
factory.StartNew(() => fitDataResulLits = CopyFitDataFiles(copyFileTaskParameters, cancellationToken));
factory.StartNew(() => decompAnalyzerStoreResultsList = CopyDecompAnalyzerFiles(copyFileTaskParameters, cancellationToken));
factory.StartNew(() => nmStoreResultsList = CopyNMStoreResultsFiles(copyFileTaskParameters, cancellationToken));
});
parent.Wait();
return null;
}
The calling code is synchronous. Execution continues in this method before the tasks above complete.
public void CreateConfigFile(CreateConfigFileParameter parameter)
{
try
{
//data for this will need to come from UI, return values will include local file paths. All copy operations will be ran on it's own thread
//return value will include local file paths
var userFileListModel = _copyFilesToLocalDirectoryService.CopyFilesAsync(temp);
//will return object graph of data read from speadsheets and excel files
_readLocalFilesToDataModelService.ReadAllFiles();
//will take object graph and do date period logic and event type compression and any other business
//logic to extract an object model to create the config file
_processDataModelsToCreateConfigService.Process();
//will take extracted object model and use config file template to create the config file workbook
_writeConfigFileService.WriteConfigFile();
}
catch(Exception ex)
{
}
}
This code is in a class library in a WPF application. I don't know if that is important, but this is the first time I have had to interact with WPF (15 years of web development only.)
What do I need to do to stop execution until all tasks have completed? I played around with a few other approaches, such as attaching as children but nothing I do seems to work.
Edit - I keep trying approaches straight out of MSDN samples with no luck whatsoever. Just tried this
var cancellationToken = new CancellationToken();
var tasks = new List<Task>();
tasks.Add(Task.Run(() =>
{
fitDataResulLits = CopyFitDataFiles(copyFileTaskParameters, cancellationToken);
}));
Task t = Task.WhenAll(tasks.ToArray());
t.Wait();
Exactly like the MSDN sample, and I tried WaitAll but it runs right past it.
Could this have something to do with the Visual Studio debugger?
Upvotes: 0
Views: 87
Reputation: 28355
There are many questions to your code:
TaskFactory
to start a background work, which is already a Task
?CancellationToken
? You need to create a CancellationTokenSource
, and use it's Token
for all your code you may need to cancel.Also, this code:
tasks.Add(Task.Run(() =>
{
fitDataResulLits = CopyFitDataFiles(copyFileTaskParameters, cancellationToken);
}));
doesn't fire the CopyFitDataFiles
, it simply assigns a task reference. You need to do this:
tasks.Add(CopyFitDataFiles(copyFileTaskParameters, cancellationToken));
Your code should be rewritten in this way:
public async Task<List<string>> CopyFilesAsync(List<ModelIterationModel> model)
{
var copyFileTaskParameters = GetCopyFileTaskParameters(model);
// do not await tasks here, just get the reference for them
var fitDataResulLits = CopyFitDataFiles(copyFileTaskParameters, cancellationToken);
// ...
// wait for all running tasks
await Task.WhenAll(copyFileTaskParameters, ...);
// now all of them are finished
}
// note sugnature change
public async Task CreateConfigFile
{
// if you really need to wait for this task after some moment, save the reference for task
var userFileListModel = _copyFilesToLocalDirectoryService.CopyFilesAsync(temp);
...
// now await it
await userFileListModel;
...
}
There is a great article about async/await: Async/Await - Best Practices in Asynchronous Programming by @StephenCleary
Upvotes: 1