Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non-Generic TaskCompletionSource or alternative

I'm working with an alert window (Telerik WPF) that is normally displayed asynchronously ( code continues running while it is open) and I want to make it synchronous by using async/await.

I have this working with TaskCompletionSource but that class is generic and returns an object like Task<bool> when all I want is a plain Task with no return value.

public Task<bool> ShowAlert(object message, string windowTitle) {     var dialogParameters = new DialogParameters { Content = message };      var tcs = new TaskCompletionSource<bool>();     dialogParameters.Closed += (s, e) => tcs.TrySetResult(true);      RadWindow.Alert(dialogParameters);      return tcs.Task; } 

The code that calls that method is

await MessageBoxService.ShowAlert("The alert text.") 

How can I return a non-generic Task that functions similarly which I can await until the dialogParameters.Closed event fires? I understand that I could just ignore the bool that is being returned in this code. I am looking for a different solution than that.

like image 638
Kevin Kalitowski Avatar asked Aug 15 '12 12:08

Kevin Kalitowski


People also ask

What is a TaskCompletionSource?

The TaskCompletionSource class is a great way to convert such code into a Task you can simply await . It's a bit of additional work, but the result is much easier to read and use. Be sure to take full advantage of TaskCompletionSource in your asynchronous C# code!

Is TaskCompletionSource thread safe?

Is it safe to pass non-thread-safe objects created on one thread to another using TaskCompletionSource. SetResult()? Yes, as long as the object can be used on a different thread than the one it was created on (of course).


2 Answers

The method can be changed to:

public Task ShowAlert(object message, string windowTitle) 

Task<bool> inherits from Task so you can return Task<bool> while only exposing Task to the caller

Edit:

I found a Microsoft document, http://www.microsoft.com/en-us/download/details.aspx?id=19957, by Stephen Toub titled 'The Task-based Asynchronous pattern' and it has the following excerpt that recommends this same pattern.

There is no non-generic counterpart to TaskCompletionSource<TResult>. However, Task<TResult> derives from Task, and thus the generic TaskCompletionSource<TResult> can be used for I/O-bound methods that simply return a Task by utilizing a source with a dummy TResult (Boolean is a good default choice, and if a developer is concerned about a consumer of the Task downcasting it to a Task<TResult>, a private TResult type may be used)

like image 83
Kevin Kalitowski Avatar answered Sep 23 '22 17:09

Kevin Kalitowski


If you don't want to leak information, the common approach is to use TaskCompletionSource<object> and complete with a result of null. Then just return it as a Task.

like image 34
Stephen Cleary Avatar answered Sep 21 '22 17:09

Stephen Cleary