I have custom control and I have interface this control exposes to it's users.
public interface ILookupDataProvider
{
string IdColumnName { get; }
IEnumerable<IDataColumn> Metadata { get; set; }
void GetDataAsync(string parameters,
Action<IEnumerable<object>> onSuccess, Action<Exception> onError);
}
So, it's my attempt to expose async operation in GetDataAsync
But I don't know how to implement this method in my class that implements interface. I understand this portion as I have method which will execute and then onCompletion
, onSucess
or onError
delegate will be called.
Can somebody help with syntax on how to write those?
EDIT:
It's 4.0 and I can't use await
commands
EDIT 2:
I use DevForce framework to load data, but for the sake of this sample - let's do WCF service for example. How would I wrap WCF service call in my interface implementation?
Also, do you think it's OK to create interface like this to present async operation? Would you do it differently with event for example?
The basic idea here is that the query will occur an a background thread. Once your operation is complete you would use the onSuccess
and onError
callbacks in order to report the new values. For example
void GetDataAsync(
string parameters,
Action<IEnumerable<object>> onSuccess,
Action<Exception> onError) {
WaitCallback doWork = delegate {
try {
IEnumerable<object> enumerable = GetTheData(parameters);
onSuccess(enumerable);
} catch (Exception ex) {
onError(ex);
}
};
ThreadPool.QueueUserWorkItem(doWork, null);
}
You really don't want to use this pattern:
void GetDataAsync(string parameters,
Action<IEnumerable<object>> onSuccess, Action<Exception> onError);
Instead, you want to use this:
Task GetDataAsync(string parameters);
In returning a Task
, you are returning an instance which represents the asynchronous unit of work. From there, the consumer of the API can choose to call ContinueWith
and decide what to do when it succeeds, or if there is an error.
However, there is a design flaw in your example. In a method named GetDataAsync
, I'd expect data to be returned. That's not a problem, you can just change the signature to:
Task<MyData> GetDataAsync(string parameters);
This now returns a Task<T>
which you can use the Result
property of to get the result (it will block if the task isn't done), or you can use the ContinueWith
method again to process the data when the async operation is done.
Additionally, you can take a CancellationToken
structure instance of a parameter to determine if you should cancel your operation:
Task<MyData> GetDataAsync(string parameters,
CancellationToken cancellationToken);
Again, ContinueWith
will allow you to indicate the action to take on cancellation.
Note that this is the way how methods using await
and async
in the Async CTP are currently being modeled; they are returning Task
or Task<T>
; doing the same in your code will allow you to be ready when these language features are baked in.
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