First of all, I am sure that this already has an answer somewhere, but I cannot find it.
I am running a parallel foreach inside a task and it is not waiting until all tasks are finished.
I have tried placing Task.Wait(); after the method, but that didn't help. I have Googled and looked on StackOverflow and I cannot figure this out. It seems like it should be simple, but I must be missing something.
var t = await Task.Run(() => Parallel.ForEach(SourceDestination, async s =>
{
bool bNeedsPassword = false;
success = ExtractReaderAPI(s.Source, s.Extension, out bNeedsPassword, s.Destination);
if (bNeedsPassword)
{
await AskForPasswordAsync(s.Source, s.Extension, s.Destination);
}
}));
DisplayMessage(m_resourceLoader.GetString("Finished"));
I removed a bunch of code from the snippet above to shorten the post. But the bottom line is, while it is asking for a password, the Finished message is being displayed. How can I wait for all of the Parallel.ForEach tasks to finish before it moves to the Finished message?
Thanks.
Edit: After trying several of the methods mentioned in the duplicate post, I still cannot achieve what I am trying to achieve.
- I need to spawn off a bunch of threads to open a bunch of files.
- If one of those files is password protected, execution will move to a catch block where a boolean will be set to true bPasswordNeeded.
- In that case, a method will be called to open a ContentDialog with a textbox asking for a password. This is an async Task
- The password will then be passed to a method to open the file.
But what is happening is the Finished dialog pops up in front of the content dialog that asks for the file password. If I close the Finished dialog and enter the password and close the password dialog, the file opens. So the worker thread awaits for the password, but before that happens, all of my tasks are marked as complete and the program execution continues on the UI thread.
I think the problem is that when I await the AskForPasswordAsync method, the Task is marked as complete. Do I have that right?
Am I approaching this correctly, or should I use a different approach?
Edit2: I just solved the problem
while(m_iThreadCounter > 0)
await Task.Factory.StartNew( () => Task.Delay(5).Wait());
workingProgressRing.IsActive = false;
DisplayMessage(m_resourceLoader.GetString("Finished"));
I have a global variable that keeps track of the number of threads that are running, so as long as that is above 0, there are still running tasks. When control moves into the threaded method, number of tasks is incremented. When the method is finished, or when control moves into a catch block in the threaded method, the number of threads running is decremented.
Wow, so simple.