Mendizalea
Mendizalea

Reputation: 53

C# sync function to async

How I can change this function to async with Framework 4.6.1? The DGV has a lot of data and blocks the rest of the processes.

DGV is updated every 30 seconds with timer.

any other solution do not block the next process until this is finnished?

I may have something wrong, I am starting in the world of programming and I have many things to learn.

private void FillTimes()
        {
            var strResponse = CallJson($"RESTAPI URL");
            if (strResponse != null)
            {
                var jResult = JsonConvert.DeserializeObject<JsonResults>(strResponse);

                BindingSource bsResults = new BindingSource();
                bsResults.DataSource = jResult.Results;

                if (bsResults.DataSource != null)
                {
                    DgvOnline.DataSource = bsResults.DataSource;
                }
            }
        }

CallJson

 private string CallJson(string strURL)
            {
                RestTiming rJson = new RestTiming();
                rJson.endPoint = strURL;
                rJson.token = apiToken;

                string strResponse = string.Empty;

                strResponse = rJson.makeRequest();

                return strResponse;
            }

ResTiming

using System;
using System.IO;
using System.Net;
using System.Windows.Forms;

namespace Timing
{
    public enum httpVerb
    {
        GET,
        POST,
        PUT,
        DELETE

    }
    class RestTiming
    {
        public string endPoint { get; set; }
        public string token { get; set; }
        public httpVerb httpMethod { get; set; }
        public string userName { get; set; }
        public string userPassword { get; set; }
        public string postJSON { get; set; }

        public RestTiming()
        {
            endPoint = string.Empty;
            token = string.Empty;
        }

        public string makeRequest()
        {
            if (InternetAvailable())
            {
                string strResponseValue = string.Empty;

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(endPoint);

                request.Method = httpMethod.ToString();
                request.ContentType = "application/json";
                request.Accept = "application/json";
                request.Headers.Add("Authorization", token);
                request.UserAgent = @"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36";

                if ((request.Method == "POST" || request.Method == "PUT") && postJSON != string.Empty)
                {
                    using (StreamWriter swJSONPayload = new StreamWriter(request.GetRequestStream()))
                    {
                        swJSONPayload.Write(postJSON);
                        swJSONPayload.Close();
                    }
                }

                HttpWebResponse response = null;

                try
                {
                    response = (HttpWebResponse)request.GetResponse();

                    // Process the response stream... (could be JSON, XML or HTML etc...)

                    using (Stream responseStream = response.GetResponseStream())
                    {
                        if (responseStream != null)
                        {
                            using (StreamReader reader = new StreamReader(responseStream))
                            {
                                strResponseValue = reader.ReadToEnd();
                            }// End of StreamReader
                        }
                    }// End of using ResponseStream

                }
                catch (WebException ex)
                {
                    if (ex.Status == WebExceptionStatus.ProtocolError && ex.Response != null)
                    {
                        var resp = (HttpWebResponse)ex.Response;
                        if (resp.StatusCode == HttpStatusCode.Unauthorized)
                        {
                            MessageBox.Show("Unauthorized", "Unauthorized", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                            Environment.Exit(1);
                        }
                    }
                }

                return strResponseValue;
            }
            else
            {
                return null;
            }
        }

        private static Boolean InternetAvailable()
        {
            try
            {
                using (WebClient client = new WebClient())
                {
                    using (client.OpenRead("http://www.google.com/"))
                    {
                        return true;
                    }
                }
            }
            catch
            {
                return false;
            }
        }
    }
}

Thanks

Upvotes: 0

Views: 1148

Answers (3)

Ajeet Kumar
Ajeet Kumar

Reputation: 729

Updated

  class RestTiming
  {
    public string endPoint { get; set; }
    public string token { get; set; }
    public httpVerb httpMethod { get; set; }
    public string userName { get; set; }
    public string userPassword { get; set; }
    public string postJSON { get; set; }

    public RestTiming()
    {
        endPoint = string.Empty;
        token = string.Empty;
    }

    public async Task<string> makeRequest() //1. Changed to async and return type
    {
        if (InternetAvailable())
        {
            string strResponseValue = string.Empty;

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(endPoint);

            request.Method = httpMethod.ToString();
            request.ContentType = "application/json";
            request.Accept = "application/json";
            request.Headers.Add("Authorization", token);
            request.UserAgent = @"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36";

            if ((request.Method == "POST" || request.Method == "PUT") && postJSON != string.Empty)
            {
                using (StreamWriter swJSONPayload = new StreamWriter(await request.GetRequestStreamAsync())) //2. changed to asynchronous call
                {
                    swJSONPayload.Write(postJSON);
                    swJSONPayload.Close();
                }
            }

            WebResponse response = null; //(a) updated

            try
            {
                response =await request.GetResponseAsync(); 

                // Process the response stream... (could be JSON, XML or HTML etc...)

                using (Stream responseStream =response.GetResponseStream()) //(b) updated
                {
                    if (responseStream != null)
                    {
                        using (StreamReader reader = new StreamReader(responseStream))
                        {
                            strResponseValue = await reader.ReadToEndAsync(); // (c) updated
                        }// End of StreamReader
                    }
                }// End of using ResponseStream

            }
            catch (WebException ex)
            {
                if (ex.Status == WebExceptionStatus.ProtocolError && ex.Response != null)
                {
                    var resp = (HttpWebResponse)ex.Response;
                    if (resp.StatusCode == HttpStatusCode.Unauthorized)
                    {
                        MessageBox.Show("Unauthorized", "Unauthorized", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                        Environment.Exit(1);
                    }
                }
            }

            return strResponseValue;
        }
        else
        {
            return null;
        }
    }

    private static Boolean InternetAvailable()
    {
        try
        {
            using (WebClient client = new WebClient())
            {
                using (client.OpenRead("http://www.google.com/"))
                {
                    return true;
                }
            }
        }

Changes in the second method

private async Task<string> CallJson(string strURL) //1. Changed to async and return type
        {
            RestTiming rJson = new RestTiming();
            rJson.endPoint = strURL;
            rJson.token = apiToken;

            string strResponse = string.Empty;

            strResponse =await rJson.makeRequest(); //2. made asynchronous 

            return strResponse;
        }

The change in the first method

    private async Task FillTimes() // 1. Make async and change return type
    {
        var strResponse =await CallJson($"RESTAPI URL"); // 2. add await to make asynchronous
        ...
    }

Please let me know if this helps. Additionally, check this link (Getting the Response of a Asynchronous HttpWebRequest)

Upvotes: 1

Silas Reinagel
Silas Reinagel

Reputation: 4223

I'm not going to weigh in on whether your code should be async or not.

If you want the synchronous work to happen in a background thread, you can execute it using Task.Run as follows:

private async Task FillTimes()
{
    return Task.Run(() => {
    {
        var strResponse = CallJson($"RESTAPI URL");
        if (strResponse != null)
        {
            var jResult = JsonConvert.DeserializeObject<JsonResults>(strResponse);

            BindingSource bsResults = new BindingSource();
            bsResults.DataSource = jResult.Results;

            if (bsResults.DataSource != null)
            {
                DgvOnline.DataSource = bsResults.DataSource;
            }
        }
    }
}

Upvotes: 2

TheGeneral
TheGeneral

Reputation: 81573

Update

If CallJson is IO Bound work then you could make that async, also you would append the Async suffix to the the method name to be consistent. Your resulting method would look like this.

private async Task FillTimes()
{
   var strResponse = await CallJsonAsync($"RESTAPI URL");
   if (strResponse != null)
   {
      var jResult = JsonConvert.DeserializeObject<JsonResults>(strResponse);

      BindingSource bsResults = new BindingSource();
      bsResults.DataSource = jResult.Results;

      if (bsResults.DataSource != null)
      {
         DgvOnline.DataSource = bsResults.DataSource;
      }
   }
}

And your async method would look like this

private async Task<responseType> CallJsonAsync(<something>)
{
    ... 

    await SomethingAsync(...);

    ...

    return something;
}

Original

How I can change this function to async with Framework 4.6.1

There is no obvious IO Bound work, and no method that would lend itself towards an async call (that i can see).

So to answer the question, "How I can change this function to async?", the answer is you shouldn't, let it be synchronous.

If this does not update the UI, you could call this method from a Task, and await that

Upvotes: 1

Related Questions