I've recently moved back to C# from being in Objective-C land, and the async/await keywords in C# 5 look cool. But I'm still trying to get a handle on the proper syntax.
I want to declare a method that takes an asynchronous delegate as a parameter, but I am having trouble getting both the caller and the callee syntax correct. Can someone provide a code sample showing the method declaration, the call, and a call to the delegate?
I'm thinking the declaration would be something like the following. Note that this function isn't asynchronous; i.e. its asynchronicity is independent of the delegate.
void DoSomethingWithCallback(async delegate foo(int)) { ... foo(42); ... }
The call would be something like:
DoSomethingWithCallback(async (int x) => { this.SomeProperty = await SomeAsync(x); });
Of course none of this compiles and most of the samples I've seen assume that one has a field or property that's the delegate, rather than the anonymous delegate I'd like to use.
Delegates enable you to call a synchronous method in an asynchronous manner. When you call a delegate synchronously, the Invoke method calls the target method directly on the current thread. If the BeginInvoke method is called, the common language runtime (CLR) queues the request and returns immediately to the caller.
The async keyword turns a method into an async method, which allows you to use the await keyword in its body. When the await keyword is applied, it suspends the calling method and yields control back to its caller until the awaited task is complete. await can only be used inside an async method.
Interfaces can't use async in a method declaration, simply because there is no need. If an interface requires that a method returns Task , the implementation may choose to use async , but whether it does or not is a choice for the implementing method. The interface doesn't need to specify whether to use async or not.
Asynchronous Programming Using Delegates. Delegates enable you to call a synchronous method in an asynchronous manner. When you call a delegate synchronously, the Invoke method calls the target method directly on the current thread.
The method that has to be passed into the AsyncCallback delegate should have a void return type and IAsyncResult as a parameter to match the delegate signature. //Target of AsyncCallback delegate should match the following pattern public void AddComplete(IAsyncResult iftAr)
When a delegate is called using BeginInvoke it has same parameters as the method that we want to execute and two other parameters. AsyncCallback :delegate that references a method to be called when the asynchronous call completes Sender Object: a user-defined object that passes information into the callback method
To call a method in an asynchronous way, you must first reference it using a delegate object which has the same signature. Then, you have to call BeginInvoke on this delegate object. As you have seen, the compiler ensures that the first arguments of the BeginInvoke method are the arguments of the method to be called.
A function that takes a delegate as a parameter must use a named delegate type; unlike in Objective-C you can't declare an anonymous delegate type inline in the function definition. However, the generics Action<> and Func<> are provided so that you don't have to declare a new type yourself. In the code below I'm assuming the delegate takes a single int
as a parameter.
void DoSomethingWithCallback(Func<int,Task> callbackDelegate) { Task t = callbackDelegate(42); }
If this function doesn't actually do anything with the Task object returned (as with the code shown above), you can instead use Action<int>
as the delegate type. If you use Action, you can still declare the delegate async (below) but the implicit Task object returned is ignored.
The lambda syntax for calling the above function is straightforward and the syntax you used in the question is correct. Note that the parameter type doesn't need to be specified here since it can be inferred:
DoSomethingWithCallback(async (intParam) => { this.myint = await Int2IntAsync(intParam); });
You can also pass a method or delegate variable, if you wish, instead of using the lambda syntax:
async Task MyInt2Int(int p) { ... } Func<int,Task> myDelegate; void OtherMethod() { myDelegate = MyInt2Int; DoSomethingWithCallback(myDelegate); // this ... DoSomethingWithCallback(MyInt2Int); // ... or this. }
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