Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# HTTP客户端在线程并行池中获取请求-随机故障_C#_Console Application_Httpclient_.net 5 - Fatal编程技术网

C# HTTP客户端在线程并行池中获取请求-随机故障

C# HTTP客户端在线程并行池中获取请求-随机故障,c#,console-application,httpclient,.net-5,C#,Console Application,Httpclient,.net 5,我有一个API,它提供了一些传感器的状态(位于Azure函数上) 我的客户端应用程序需要每秒钟检查一次每个传感器!因此,在本例中,我有10个传感器,客户端需要每秒发送10个http get请求 我决定使用Parallel来实现这一点,并从我的方法的每个实例中创建一个池,该方法运行一个执行Get请求的实例 这是一个主要的方法,它协调并将每个传感器添加到池中,并调用它们 public override Task Run(List<int> sensors)

我有一个API,它提供了一些传感器的状态(位于Azure函数上)

我的客户端应用程序需要每秒钟检查一次每个传感器!因此,在本例中,我有10个传感器,客户端需要每秒发送10个http get请求

我决定使用Parallel来实现这一点,并从我的方法的每个实例中创建一个池,该方法运行一个执行Get请求的实例

这是一个主要的方法,它协调并将每个传感器添加到池中,并调用它们


        public override Task Run(List<int> sensors)
        {
            try
            {
                List<Action> actions = new List<Action>();
                foreach (var prd in sensors)
                {
                    actions.Add(async () => await Process(prd));
                }
                ParallelOptions parallelOptions = new ParallelOptions
                {
                    MaxDegreeOfParallelism = 20 
                };
                Parallel.Invoke(parallelOptions, actions.ToArray());
            }
            catch (Exception ex)
            {
                Run(sensors);
            }
            return Task.CompletedTask;
        }

我知道它在我的GetAsync方法中,但我不明白为什么它在运行几分钟后发生,而不仅仅是从一开始

还请注意,我必须通过调用使我的GetAsync方法不异步。结果就像我在等待一样,然后应用程序在启动第一个请求之前崩溃!似乎它不喜欢在并行池中被调用

谢谢你的帮助

更新了更多详细信息:

HttpClientService.cs


    public class HttpClientService : IHttpClientService
    {
        private readonly HttpClient _client;
        private readonly ILogger<HttpClientService> _logger;
        private static readonly JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };


        public HttpClientService(HttpClient client, ILogger<HttpClientService> logger)
        {
            _client = client;
            _logger = logger;
        }
.
.
.


公共类HttpClientService:IHttpClientService
{
私有只读HttpClient\u客户端;
专用只读ILogger\u记录器;
私有静态只读JsonSerializerSettings JsonSerializerSettings=new JsonSerializerSettings{NullValueHandling=NullValueHandling.Ignore};
公共HttpClientService(HttpClient客户端,ILogger记录器)
{
_客户=客户;
_记录器=记录器;
}
.
.
.
这就是我注册HttpClient的方式

            services.AddHttpClient<IHttpClientService, HttpClientService>();

services.AddHttpClient();

以下是一些一般准则:

  • 。您的代码当前正在将
    async
    lambdas添加为
    Action
    委托,其结果是
    async void
  • 。也就是说,不要阻塞
    async
    code。特别是,不要使用
    .Result
  • 最后,
    Parallel
    不会与
    async
    混用,因为
    Parallel
    用于CPU绑定的多线程并行,而不是I/O绑定的无线程异步。您需要的解决方案是异步并发,即
    Task.whalll

    public override async Task Run(List<int> sensors)
    {
      var tasks = sensors
          .Select(prd => Process(prd))
          .ToList();
      await Task.WhenAll(tasks);
    }
    
    private async Task<string> Process(int sensorId)
    {
      while (true)
      {
        await Task.Delay(1000);
        try
        {
          SensorModel response = await _httpClientService.GetAsync<SensorModel>(string.Format(apiUrl, sensorId));
          if (response != null)
          {
            if (response.Status == "success")
            {
              ...
            }
            _logger.LogError($"API connection unsuccesful...");
            return null;
          }
          _logger.LogError($"API connection failed...");
          return null;
        }
        catch (Exception ex)
        {
          _logger.LogError($"Exception in retrieving sensor data {StringExtensions.GetCurrentMethod()} {ex}");
          return null;
        }
      }
    }
    
    公共覆盖异步任务运行(列出传感器)
    {
    var任务=传感器
    .选择(prd=>过程(prd))
    .ToList();
    等待任务。何时(任务);
    }
    专用异步任务进程(int-sensorId)
    {
    while(true)
    {
    等待任务。延迟(1000);
    尝试
    {
    SensorModel response=wait_httpClientService.GetAsync(string.Format(apirl,sensorId));
    if(响应!=null)
    {
    如果(response.Status==“success”)
    {
    ...
    }
    _logger.LogError($“API连接未成功…”);
    返回null;
    }
    _logger.LogError($“API连接失败…”);
    返回null;
    }
    捕获(例外情况除外)
    {
    _logger.LogError($“检索传感器数据时发生异常{StringExtensions.GetCurrentMethod()}{ex}”);
    返回null;
    }
    }
    }
    
    如何将HttpClient注入您的HttpClientService?如何将您的服务添加到DI?请更新您的问题完成,感谢@saeedesmaeelinejaddin而不是使用
    线程。睡眠(1000);
    使用此
    等待任务。延迟(1000)
    然后测试它的安全性,现在就去尝试它不起作用,它经历了一个循环,然后就存在了,我认为这是因为在延迟之后它返回一个任务,当Run方法得到一个任务时,它假设应用程序已经完成了执行!非常感谢,我没有意识到异步无效!它现在正在按预期工作!
    
        public class HttpClientService : IHttpClientService
        {
            private readonly HttpClient _client;
            private readonly ILogger<HttpClientService> _logger;
            private static readonly JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
    
    
            public HttpClientService(HttpClient client, ILogger<HttpClientService> logger)
            {
                _client = client;
                _logger = logger;
            }
    .
    .
    .
    
    
                services.AddHttpClient<IHttpClientService, HttpClientService>();
    
    
    public override async Task Run(List<int> sensors)
    {
      var tasks = sensors
          .Select(prd => Process(prd))
          .ToList();
      await Task.WhenAll(tasks);
    }
    
    private async Task<string> Process(int sensorId)
    {
      while (true)
      {
        await Task.Delay(1000);
        try
        {
          SensorModel response = await _httpClientService.GetAsync<SensorModel>(string.Format(apiUrl, sensorId));
          if (response != null)
          {
            if (response.Status == "success")
            {
              ...
            }
            _logger.LogError($"API connection unsuccesful...");
            return null;
          }
          _logger.LogError($"API connection failed...");
          return null;
        }
        catch (Exception ex)
        {
          _logger.LogError($"Exception in retrieving sensor data {StringExtensions.GetCurrentMethod()} {ex}");
          return null;
        }
      }
    }