通过C#同步功能进行异步

时间:2019-03-19 22:53:59

标签: c# asynchronous async-await

如何将此功能更改为与Framework 4.6.1异步? DGV具有大量数据,并会阻止其余过程。

DGV每30秒更新一次带有计时器。

任何其他解决方案在完成后才阻止下一步吗?

我可能出了点问题,我是从编程领域开始的,我有很多东西要学习。

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;
            }

重新计时

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;
            }
        }
    }
}

谢谢

3 个答案:

答案 0 :(得分:1)

更新

如果CallJson IO Bound 工作,那么您可以使该async,也可以将后缀Async附加到方法名称上以保持一致。您产生的方法将如下所示。

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;
      }
   }
}

您的async方法看起来像这样

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

    await SomethingAsync(...);

    ...

    return something;
}

原始

  

如何将此功能更改为与Framework 4.6.1异步

没有明显的 IO Bound 工作,也没有任何方法可以使自己进行async调用(我可以看到)。

所以要回答“ 如何将这个功能更改为async”这个问题,答案是您不应该让它同步。

如果这不会更新 UI ,则可以从Taskawait调用此方法

答案 1 :(得分:1)

我不会考虑您的代码是否应该异步。

如果您希望同步工作在后台线程中进行,则可以使用Task.Run如下执行它:

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;
            }
        }
    }
}

答案 2 :(得分:1)

已更新

  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;
                }
            }
        }

第二种方法的更改

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;
        }

第一种方法的变化

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

请告诉我这是否有帮助。 此外,请检查此链接(Getting the Response of a Asynchronous HttpWebRequest