0

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

Mendizalea
  • 53
  • 8

3 Answers3

2

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;
            }
        }
    }
}
Silas Reinagel
  • 4,155
  • 1
  • 21
  • 28
  • You should also note, wrapping/offloading CPU bound workloads in the implementation of an `async` method is a code smell and is called *fake async*, its confusing, its not scalable, it uses up valuable thread-pool threads and can have unintended consequences. Even if this is IO bound, its very suspicious and should be warned against – TheGeneral Mar 19 '19 at 23:25
  • @MichaelRandall Certainly. I completely agree. Most beginners are looking to StackOverflow for simple solutions to simple problems. StackOverflow isn't supposed to be an extensive curriculum. If your detailed answer and warnings are what the OP desires, then they can mark your answer as accepted. If the OP wants a simple answer that doesn't go into the numerous flaws and gotchas of `async/await/TPL` then this answer is perfect. – Silas Reinagel Mar 19 '19 at 23:34
  • @MichaelRandall Well, what's the alternative to `Task.Run()` for CPU-bound computation? `BackgroundWorker`? No thank you. – Joker_vD Mar 20 '19 at 19:23
  • @Joker_vD you missed the point, you just should wrap CPU bound in a task then call it an async method, let the method be syncronions let the caller call task run. For all the reasons I stated – TheGeneral Mar 20 '19 at 21:49
1

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

TheGeneral
  • 79,002
  • 9
  • 103
  • 141
1

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)

Ajeet Kumar
  • 687
  • 6
  • 12
  • Thanks you, but I have problems with the first method that you change, with the 3 and 4 changes. **3** you can not convert the type 'System.Threading.Tasks.Task ' into 'System.Net.HttpWebResponse'**4** "HttpWebResponse" does not contain a definition for "GetResponseStreamAsync" – Mendizalea Mar 20 '19 at 06:59
  • I updated the code with comments, please try and let me know if it works. – Ajeet Kumar Mar 20 '19 at 07:25