Reputation: 3294
I have a switch language helper, I wrote like
public static async Task SelectLanguage()
{
//Some extra code
string strTitle = await LanService.Get("select_language");
ListDialogControl dialog = new ListDialogControl(strTitle, list, index);
dialog.Show();
dialog.Result += async (s) =>
{
**//How to pass this returned variable s to SelectLanguage()**
};
}
Now I want to change SelectLanguage() from Task to Task《string》, which return my dialog's result.
And for ListDialogControl, it's a user control.
public sealed partial class ListDialogControl : UserControl
{
Popup popup;
int ListSelectedIndex;
List<string> myList = new List<string>();
public Action<string> Result { get; set; }
/// <summary>
/// Title
/// List<string>
/// selectedIndex, -1 no need to select. if u want to select an item, selectedIndex must >= 0
/// </summary>
/// <param name="strTitle"></param>
/// <param name="list"></param>
/// <param name="selectedIndex"></param>
public ListDialogControl(string strTitle, List<string> list, int selectedIndex = -1, bool showTick = true)
{
this.InitializeComponent();
popup = Globals.popup;
popup.Child = this;
popup.Closed += Popup_Closed;
this.Loaded += ControlWindow_Loaded;
this.Unloaded += ControlWindow_Unloaded;
this.PreviewKeyDown += ControlWindow_PreviewKeyDown;
Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated += Dispatcher_AcceleratorKeyActivated;
this.Width = Window.Current.Bounds.Width;
this.Height = Window.Current.Bounds.Height;
TextBlockTip.Text = strTitle;
myList = list;
}
#region ShowHide
public void Show()
{
popup.IsOpen = true;
}
public void Hide(string result)
{
if (popup.IsOpen == false)
return;
popup.IsOpen = false;
myList.Clear();
TextBlockTip.Text = "";
Result?.Invoke(result);
}
#endregion
}
Upvotes: 1
Views: 188
Reputation: 169150
An alternative to using a TaskCompletionSource
is to use a SemaphoreSlim
to wait asynchronously until you have a value to return:
public static async Task<string> SelectLanguage()
{
string strTitle = await LanService.Get("select_language");
string result = null;
using (SemaphoreSlim semaphore = new SemaphoreSlim(0, 1))
{
ListDialogControl dialog = new ListDialogControl(strTitle, list, index);
dialog.Show();
dialog.Result += async (s) =>
{
//...
result = s;
semaphore.Release();
};
await semaphore.WaitAsync();
}
return result;
}
Upvotes: 1
Reputation: 3701
You can use a TaskCompletionSource
to achive this. Here are two options how you can implement this. Be sure to read the docs about it to ensure, you know how to handle the different states of a task.
Option 1: Use a TaskCompletionSource
inside the method
public static async Task SelectLanguage()
{
var tcs = new TaskCompletionSource<string>();
ListDialogControl dialog = new ListDialogControl(strTitle, list, index);
dialog.Show();
dialog.Result += async (s) =>
{
// This will notify the caller that the task just completed
tcs.SetResult(s);
};
// Here you can wait until the task completes
var yourResult = await tcs.Task;
}
Option 2: Use a TaskCompletionSource inside the UserControl
public class YourUserControl : UserControl
{
private TaskCompletionSource<string> _resultTask;
public Task<string> Show()
{
_resultTask = new TaskCompletionSource<string>();
return _resultTask.Task;
}
public void Hide(string result)
{
_resultTask.SetResult(result);
}
}
And now you don't need to create a TaskCompletionSource everytime:
public async Task TestMethod()
{
var dialog = new YourUserControl();
// Show dialog and wait here until the usercontrol completes the task
var result= await dialog.Show();
}
Upvotes: 2