我有一个切换语言助手,写得像
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()**
};
}
现在我想将SelectLanguage()从Task更改为Task《字符串》,这将返回对话框的结果。
对于ListDialogControl,它是一个用户控件。
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
}
答案 0 :(得分:2)
您可以使用TaskCompletionSource
来达到目的。这是两种实现方法。请务必阅读有关此文档,以确保您知道如何处理不同的states of a task。
选项1:在方法内使用TaskCompletionSource
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;
}
选项2:在UserControl中使用TaskCompletionSource
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);
}
}
现在您无需每次都创建TaskCompletionSource:
public async Task TestMethod()
{
var dialog = new YourUserControl();
// Show dialog and wait here until the usercontrol completes the task
var result= await dialog.Show();
}
答案 1 :(得分:1)
使用TaskCompletionSource
的另一种方法是使用SemaphoreSlim
异步等待,直到您有返回值:
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;
}