[SOLVED] Async method is working as syncronous mehtod

Issue

I am trying to call a async method of ViewModel from another method in View but it is behaving as syncronous.

View Model:

public async Task<bool> GetReadyForUnlockWithQR()
    {
        try
        {
            SmilaHash = GetRandomeHashKey();
            var data = JsonConvert.SerializeObject(GetSmilaInfo());
            var res = await apiClient.PostAsync<String>("readyforunlockwithqr", data);
            if (res != null)
            {
                JObject json = JObject.Parse(res);
                if (json["doUnlock"] != null)
                {
                    LoginStatus = json.SelectToken("doUnlock").Value<bool>();
                }
            }
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
            CancelPendingRequests();
            throw ex;
        }
        return false;
    }

I have my api methods defined in a custome APIClient file. The above request may take a minute to complete. I don’t want to stop the UI and perform my further operations in View. Following is my View:

private async void UnlockButton_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            await ViewModel.GetReadyForUnlockWithQR();
            DisplayQRCode();
        }
        catch(Exception ex)
        {
            if (ex is HttpRequestException)
            {
                Debug.WriteLine("Server not reachable");
                MessageBox.Show("Server not reachable");
            }
            else if (ex is OperationCanceledException)
            {
                Debug.WriteLine("Timeout exception");
                QRCodeImage.Source = null;
                QRCodeCanvas.Visibility = Visibility.Hidden;
            }
            else
            {
                Debug.WriteLine(ex.Message);
            }
        }
    }

I above code ideally the DisplayQRCode() function should work immediately after await ViewModel.GetReadyForUnlockWithQR(); but it is not happening. The DisplayQRCode() is waiting to receive response from ViewModel.GetReadyForUnlockWithQR() Why is this not behaving as logical asyn code.

Solution

The DisplayQRCode() is waiting to receive response from ViewModel.GetReadyForUnlockWithQR() Why is this not behaving as logical asyn code.

The asynchronous method is behaving serially (not "synchronously"), which is exactly what await is supposed to do.

You can think of await as "asynchronous wait": the method is paused and will not continue pass the await until the task completes, but it waits asynchronously, so the thread is freed (the method returns to its caller).

I above code ideally the DisplayQRCode() function should work immediately after await ViewModel.GetReadyForUnlockWithQR(); but it is not happening.

If you want to do that, then you can call GetReadyForUnlockWithQR but don’t await the task until after DisplayQRCode completes:

var getReadyTask = ViewModel.GetReadyForUnlockWithQR();
DisplayQRCode();
await getReadyTask;

Answered By – Stephen Cleary

Answer Checked By – Terry (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *