What would be the best way to convert/wrap a "classic" asynchronous method that uses a callback to something that returns a (awaitable) Task?
For example, given the following method:
public void GetStringFromUrl(string url, Action<string> onCompleted);
The only way I know of to wrap this into a method returning a task is:
public Task<string> GetStringFromUrl(string url) { var t = new TaskCompletionSource<string>(); GetStringFromUrl(url, s => t.TrySetResult(s)); return t.Task; }
Is this the only way to accomplish this?
And is there a way to wrap the call to GetStringFromUrl(url,callback) in the task itself (i.e. the call itself would run inside the task instead of synchronously)
For methods other than event handlers that don't return a value, you should return a Task instead, because an async method that returns void can't be awaited. Any caller of such a method must continue to completion without waiting for the called async method to finish.
Callbacks are not asynchronous by nature, but can be used for asynchronous purposes. In this code, you define a function fn , define a function higherOrderFunction that takes a function callback as an argument, and pass fn as a callback to higherOrderFunction .
The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't expected.
The differences between asynchronous and synchronous include: Async is multi-thread, which means operations or programs can run in parallel. Sync is single-thread, so only one operation or program will run at a time. Async is non-blocking, which means it will send multiple requests to a server.
Your code is short, readable and efficient, so I don't understand why are you looking for alternatives, but I can't think of anything. I think your approach is reasonable.
I'm also not sure why do you think that the synchronous part is okay in the original version, but you want to avoid it in the Task
-based one. If you think the synchronous part might take too long, fix it for both versions of the method.
But if you want to run it asynchronously (i.e. on the ThreadPool
) only in the Task
version, you can use Task.Run()
:
public Task<string> GetStringFromUrl(string url) { return Task.Run(() => { var t = new TaskCompletionSource<string>(); GetStringFromUrl(url, s => t.TrySetResult(s)); return t.Task; }); }
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