简体   繁体   中英

Async/Await with RestSharp in Windows Phone 8

I did search this all over the internet, there are solutions for Windows Phone 7 but they don't work with Windows Phone 8 so please help me out with what I'm doing wrong. I'm writing a WP8 app that consumes an API from Mashape. I'm using the RestSharp NuGet package. Here are my extension methods for RestSharp packages to await.

public static class RestClientExtensions
{
    public static Task<IRestResponse> ExecuteTaskAsync(this RestClient @this, RestRequest request)
    {
        if (@this == null)
            throw new NullReferenceException();

        var tcs = new TaskCompletionSource<IRestResponse>();

        @this.ExecuteAsync(request, (response) =>
        {
            if (response.ErrorException != null)
                tcs.TrySetException(response.ErrorException);
            else
                tcs.TrySetResult(response);
        });

        return tcs.Task;
    }

    public static Task<T> ExecuteTaskAsync<T>(this RestClient @this, RestRequest request) where T : new()
    {
        if (@this == null)
            throw new NullReferenceException();

        var tcs = new TaskCompletionSource<T>();

        @this.ExecuteAsync<T>(request, (response) =>
        {
            if (response.ErrorException != null)
                tcs.TrySetException(response.ErrorException);
            else
                tcs.TrySetResult(response.Data);
        });

        return tcs.Task;
    }
}

Here is the function in which it is being called. The function lies in a API.cs class file.

public async Task<SendMessage> SendMessage(String phone, String msg, TextBox textBox)
{
    // Create a POST request with the required headers & parameters
    var request = new RestRequest("sendsms/{api}.json", Method.POST);
    request.AddUrlSegment("api", apiKey);
    request.AddHeader("X-Mashape-Key", "abcdefghixyz");
    request.AddParameter("msg", msg);
    request.AddParameter("phone", phone);

    var temp = await client.ExecuteTaskAsync<SendMessage>(request);
    return temp;
}

Here is finally the Page1.xaml.cs file where all of this is needed.

private void appBarButton_Send_Click(object sender, EventArgs e)
{
    Api api = new Api();
    SendMessage a = api.SendMessage(contactNumber, textBox_Message.Text, textBox_Message).Result;
    MessageBox.Show(a.message);
}

If I directly call the RestSharp .ExecuteAsync() method in SendMessage() method it works fine. If I do it this way, it executes up till the await condition, returns the tcs.Task and then the complete app just halts. It stays that way and nothing changes. Any idea what I am doing wrong?

I would try and await the return from SendMessage

 private async void appBarButton_Send_Click(object sender, EventArgs e)
  {
      Api api = new Api();
      SendMessage a = await api.SendMessage(contactNumber, textBox_Message.Text, textBox_Message);
      MessageBox.Show(a.message);
  }

You've introduced UI thread deadlock by this code. await in SendMessage() method is trying to marshal continuation task to calling context, which is UI context. But UI context is already blocked by waiting of the task result in SendMessage(...).Result call. 1. You should always use ConfigureAwait(false) method for awaitable object if you don't need it to marshal back to calling context, to avoid such deadlocks. The only place in your code where you need this marshaling is button click handler, because you have to interact with UI controls here. SendMessage() method should be looking like this: var temp = await client.ExecuteTaskAsync(request).ConfigureAwait(false); 2. You shouldn't use .Result or .Wait() for async methods. Yor're loosing any sense of async programming when doing this. Always use await for async methods call.

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