If I understand the question correctly, you increase the counter when starting tasks A and when each task is completed, you decrease the counter in the event handler. Also in the event handler you check (after decreasing the counter) if the counter is zero. If so, you complete task B.
I suggest you look at Tasks (also called "Parallel Task Library (TPL)"), which allows you to do something like this:
Task.WhenAll( new Task[] { Task.Run(()=> { //... do work A1... }, Task.Run(()=> { //... do work A2... }, Task.Run(()=> { //... do work A3... }}) .ContinueWith(()=> {//... do work B... });
Update: Based on the mention of the WPF animation in your comment below, Task.Run may NOT work. If I remember correctly, you get a Completed event and you cannot run the animation synchronously in the code (as in "... do work A1 ...").
However, instead of creating tasks using Task.Run you can create them from the Completed Storyboard event using the extension method, for example:
public static Task<Storyboard> BeginAsync(this Storyboard sb) { var tcs = new TaskCompletionSource<Storyboard>(); sb.Completed += (s, a) => tcs.TrySetResult(sb); sb.Begin(); return tcs.Task; }
Note that this method creates a task that is completed in the Completed storyboard event handler and starts the storyboard animation before returning the task. Also note that you can write a similar extension method for other types and events.
You should use this method, for example:
var sb1 = (Storyboard)mainWindow.FindResource("Storyboard1"); var sb2 = (Storyboard)mainWindow.FindResource("Storyboard2"); var sb3 = (Storyboard)mainWindow.FindResource("Storyboard3"); Task.WhenAll( new Task[] { sb1.BeginAsync(), sb2.BeginAsync(), sb3.BeginAsync() }) .ContinueWith(() => MessageBox.Show("All done!"), TaskScheduler.FromCurrentSynchronizationContext());
TaskScheduler.FromCurrentSynchronizationContext() basically schedules the continuation task to run in the user interface thread (which is required if you will be accessing user interface elements).