public class FooDataRepository
{
private MyServiceReferenceClient Client { get; set; }
public void FooClass()
{
Client = new MyServiceReferenceClient();
Client.SaveFooCompleted += Client_SaveFooCompleted;
Client.SaveBarCompleted += Client_SaveBarCompleted;
}
private void Client_SaveFooCompleted(Object sender, EventArgs e) { ... }
private void Client_SaveBarCompleted(Object sender, EventArgs e) { ... }
public void SaveFoo(Foo foo)
{
Client.SaveFooAsync(foo);
foreach (var bar in foo.Bars)
Client.SaveBarAsync(bar);
}
}
I want to do something within the FooDataRepository class once the SaveFooAsync
and the all the SaveBarAsync
methods have completed. Is there a standard pattern for trying to do a single thing based upon N number of Async calls completing?
You can use TaskFactory.ContinueWhenAll to schedule a code to run when all tasks have completed.
Task[] tasks = new Task[3]
{
Task.Factory.StartNew(() => MethodA()),
Task.Factory.StartNew(() => MethodB()),
Task.Factory.StartNew(() => MethodC())
};
//This will not block.
Task.Factory.ContinueWhenAll(tasks, completedTasks => { RunSomeMethod(); });
EDIT:
Regarding your question about composing async method calls with tasks if the class has Begin/End methods for calling the method in an async way you can use Task.FromAsync
Alternatively you can also use Rx for calling several methods asynchronously and then observing when all of them have completed. Have a look at this question: Can I shortcut the Begin/End async pattern by using an event to create my AsyncResult? (C# .Net 3.5, WCF)
If you can, use Tasks and then do Task.WaitAll
. E.g.:
Task[] tasks = new Task[3]
{
Task.Factory.StartNew(() => MethodA()),
Task.Factory.StartNew(() => MethodB()),
Task.Factory.StartNew(() => MethodC())
};
//Block until all tasks complete.
Task.WaitAll(tasks);
// Continue on this thread...
If you don't have access to the synchronous methods, you can use a method like the one described at Tasks and the Event-based Asynchronous Pattern to convert your EAP library into one that uses tasks. Alternately, Rx provides several ways to deal with this issue.
Basically, the best practice advice is to use Tasks if you can. If your application requires more fine-grained control, look seriously into Rx - it provides LINQ filtering for events and async methods.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With