【问题标题】:How to optimize this code and call Api every 40ms如何优化此代码并每 40ms 调用一次 Api
【发布时间】:2020-10-02 20:37:39
【问题描述】:

我想询问一个返回 JSON Rest Api 响应的传感器。我每 40 毫秒调用一次 Api,但它给了我这个错误:

在 System.Threading.Tasks.Task1.get_Result() 中的 System.Threading.Tasks.Task1.GetResultCore(Boolean waitCompletionNotification) 中

我有 interval = 40 的计时器。这就是我如何调用 tha Api 的代码:

 private void Timer(object sender, EventArgs e)
        {
            tmrPollingSick.Stop();

            string strJson = "";
           
            HttpClient client = new HttpClient();
            string baseUrl = "http://9999.99999.99999.8";
            client.BaseAddress = new Uri(baseUrl);
            var contentType = new MediaTypeWithQualityHeaderValue("application/json");
            client.DefaultRequestHeaders.Accept.Add(contentType);
            string strAltezza = string.Empty;
            try
            {
                strJson = "Here I set HEADERS... DATA ect " + Convert.ToChar(34) +
                        "header" + Convert.ToChar(34) + ": {............" 

                var contentData = new StringContent(strJson, System.Text.Encoding.UTF8, "application/json");
                using (var responseMessage = client.PostAsync("/bla/bla/bla", contentData).Result)
                {
                    if (responseMessage.IsSuccessStatusCode)
                    {
                        string strContext = responseMessage.Content.ReadAsStringAsync().Result;

                        Object dec = JsonConvert.DeserializeObject(strContext);     // deserializing Json string (it will deserialize Json string)

                        JObject obj = JObject.Parse(strContext);
                        //Process Data In
                        JObject obj1 = JObject.Parse(obj["bla"].ToString());
                        JObject obj2 = JObject.Parse(obj1["processDataIn"].ToString());
                        strAltezza = obj2["1"].ToString();
                        textBox1.Text = strAltezza;

                    }
                }
            }

        catch(WebException ex1)
        {
            MessageBox.Show("web: "+ex1.StackTrace.ToString() + " - " + ex1.Message);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.StackTrace.ToString() + " - " + ex.Message);
        }
        tmrPollingSick.Start();
    }

一切正常,但过了一段时间它给了我这个错误。 我已经读过这个(How to implement real time data for a web pagethis),但我还没有尝试过。 任何建议如何解决这个问题? 有没有其他方法可以在不崩溃的情况下实时获得结果?

【问题讨论】:

  • 记录并发布完整的。例外,而不仅仅是它的一部分。您发布的内容仅包含堆栈跟踪中的 2 行。使用.Result肯定是错误的,但现在无法猜测到底出了什么问题。你达到了服务器的限制?创建一个新的 HttpClient 而不是重用同一个实例会导致套接字耗尽?其他问题?
  • 顺便说一句,一旦你解析了一个 JSON 字符串,再次解析它的元素是没有意义的。不过,在您的代码中,您同时使用了JsonConvert JObject.Parse,因此两次解析相同的响应。
  • Http 不是一个好的选择,它每次都建立一个连接并且加上所有开销......你应该考虑使用 SignalR 或类似的东西
  • @PatrickBeynio 代替 Http 我还能用什么?

标签: c# api rest


【解决方案1】:

我可以将其称为顽固的池吗?

  1. 您不想使用计时器。您想要的是请求-响应周期之间的 x 时间。 (这将解决套接字耗尽的问题)。
  2. 将您的代码分成多个阶段(客户端初始化、请求获取、响应处理)。请参阅@Oliver 答案。
  3. 创建一个函数来执行一切。并运行某种 infinite foreach 循环,您可以在调用 fetch 函数(和进程,但您可以将其推迟到另一个线程或异步执行)后休眠 x 时间。李>

【讨论】:

    【解决方案2】:

    当您在 40 毫秒内调用此方法时,您将用完发送套接字,因为您每次都会创建一个新的 HttpClient。即使将其放入using 语句中(因为HttpClient 实现IDisposable)也不能解决这个问题,因为底层套接字将被操作系统阻塞3 分钟(查看this answer 以获得进一步的解释)。

    你应该把这些东西分成一些初始化阶段,在那里你设置客户端,尽可能建立请求,在这个计时器方法中,只需调用PostAsync() 方法并检查响应。

    【讨论】:

    • 我把它放在using 中,不再给我那个错误了。但是响应时间是200ms。不知道怎么优化
    猜你喜欢
    • 2011-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多