简体   繁体   中英

Using async await C# Xamarin

I have started using Xamarin recently and I am quite new to c#. I want to create an asynchronous HTTP request, so I started using async and await with HttpWebRequest. But I don't get an asynchronous called, the UI is getting block. This is the code I'm testing. I have two implementation the RequestCitas() should be asynchronous and the SRequestCitas() is synchronous, what is wrong?.

namespace mc
{
[Activity (Label = "mc", MainLauncher = true, Theme="@android:style/Theme.Holo.Light")]
public class MainActivity : Activity
{

    List<Cita> citas;
    CitaAdapter adapter;

    protected override void OnCreate (Bundle savedInstanceState)
    {
        base.OnCreate (savedInstanceState);
        SetContentView (Resource.Layout.Main);


        citas = new List<Cita> ();
        adapter = new CitaAdapter (this, citas);
        ListView listView = FindViewById<ListView> (Resource.Id.main_citas);
        listView.Adapter = adapter;

        var c1 = new Cita (0, "ernesto", "De los Santos", "19/2/14", "19/2/14", "09:28", "10:45");
        var c2 = new Cita (1, "ernesto", "De los Santos", "19/2/14", "19/2/14", "09:28", "10:45");
        var c3 = new Cita (2, "ernesto", "De los Santos", "19/2/14", "19/2/14", "09:28", "10:45");
        var c4 = new Cita (3, "ernesto", "De los Santos", "19/2/14", "19/2/14", "09:28", "10:45");
        var c5 = new Cita (4, "ernesto", "De los Santos", "19/2/14", "19/2/14", "09:28", "10:45");

        citas.Add (c1);
        citas.Add (c2);
        citas.Add (c3);
        citas.Add (c4);
        citas.Add (c5);

        Console.WriteLine ("Notificando al adaptador");
        adapter.NotifyDataSetChanged ();

        string result;

        FindViewById<Button> (Resource.Id.button1).Click += async (sender, e) => {
            result =  await RequestCitas ();
        };
        FindViewById<Button> (Resource.Id.button2).Click += delegate {
            result = SRequestCitas ();
        };
    }

    private async Task<string>  RequestCitas ()
    {

        // var url = "http://192.168.1.126:8081";
        var url = "http://192.168.1.124";
        //var method = "/citas/get";
        var method = "";

        var encoding = new UTF8Encoding ();
        byte[] parametros = encoding.GetBytes ("usersID=97");

        var request = (HttpWebRequest)WebRequest.Create (url + method);
        request.Method = "POST";
        request.ContentType = "application/x-www-form-urlencoded";
        request.ContentLength = parametros.Length;

        var dataStream = request.GetRequestStream ();
        dataStream.Write (parametros, 0, parametros.Length);
        dataStream.Close ();

        string str = ""; 

        Task<WebResponse> task = request.GetResponseAsync ();

        WebResponse newResponse = await task;

        var responseStream = newResponse.GetResponseStream ();
        var streamReader = new StreamReader (responseStream, System.Text.Encoding.GetEncoding ("utf-8"));
        char[] read = new Char[256];
        int count = streamReader.Read (read, 0, 256);

        while (count > 0) {
            str += new string (read, 0, count);
            count = streamReader.Read (read, 0, 256);
        }
        responseStream.Close ();

        return str;
    }


    private string SRequestCitas ()
    {

        var url = "http://192.168.1.126:8081";
        var method = "/citas/get";

        var encoding = new UTF8Encoding ();
        byte[] parametros = encoding.GetBytes ("usersID=97");

        var request = (HttpWebRequest)WebRequest.Create (url + method);
        request.Method = "POST";
        request.ContentType = "application/x-www-form-urlencoded";
        request.ContentLength = parametros.Length;

        var dataStream = request.GetRequestStream ();
        dataStream.Write (parametros, 0, parametros.Length);
        dataStream.Close ();

        string str = ""; 

        HttpWebResponse newResponse = (HttpWebResponse)request.GetResponse ();

        var responseStream = newResponse.GetResponseStream ();
        var streamReader = new StreamReader (responseStream, System.Text.Encoding.GetEncoding ("utf-8"));
        char[] read = new Char[256];
        int count = streamReader.Read (read, 0, 256);

        while (count > 0) {
            str += new string (read, 0, count);
            count = streamReader.Read (read, 0, 256);
        }
        responseStream.Close ();

        return str;
    }

}
}

You're getting response using an async method, but you're reading the stream using synchronous stream operations. Try using streamReader.ReadAsync instead.

Or, if you're feeling ambitious, you could try replacing your whole while loop altogether and use:

var str = await streamReader.ReadToEndAsync();

On a side note, StreamReader implements IDisposable and you're not properly disposing of the instance when you're done with it. You could be leaking native resources.

When you create a method which uses the await keyword, it has to me be marked as async for the compiler to allow the use of the keyword. More over, you should follow the guidelines and end your method with the Async prefix

Your async method is reading synchronously from the from the StreamReader which is causing your UI to block.

Here's a async implementation using HttpClient :

private async Task<string> RequestCitasAsync()
{
    var url = "http://192.168.1.126:8081/citas/get";
    byte[] parametros = Encoding.UTF8.GetBytes("usersID=97");

    var httpClient = new HttpClient();
    var response = await httpClient.PostAsync(url, new ByteArrayContent(parametros));

    return await response.Content.ReadAsStringAsync();
}

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