简体   繁体   中英

How to get the result of an async call?

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
}

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();
}

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM