Выбрасывание исключения через некоторое время

#c# #.net #timer #async-await #put

#c# #.net #таймер #асинхронный -ожидание #положить

Вопрос:

Я подключаюсь к устройству, используя команду ввода по URL. Однако для настройки требуется, чтобы команда была асинхронной, чтобы находиться внутри таймера. Затем некоторое время все работает нормально mscorlib.dll начинает генерировать исключения, и команды перестают отправляться.

Я попытался добавить асинхронность в обработчик событий таймера и ожидать перед функцией, вызывающей команду, но это все равно происходит. Не уверен на 100%, как это должно быть, потому что таймер не может ждать, и это происходит очень быстро.

 button click {
_updateTimer = new Timer(_updateInterval);
_updateTimer.Tick  = new EventHandler(TimerUpdate_Tick);
Start
}

private async void TimerUpdate_Tick(object sender, System.EventArgs e)
{
   //do other very important stuff that has to be in timer update event
   await myfunction();
}

public static async Task myfunction()
{
    HttpClientHandler handler = new HttpClientHandler();

    using (var httpClient = new HttpClient(handler))
    {
       using (var request = new HttpRequestMessage(new HttpMethod("PUT"), address))
       {
           request.Content = new StringContent("hello");
           var response = await httpClient.SendAsync(request);
           //after some time, it gives an exception on this SendAsync saying connection closed. I did try reconnecting but still gives it again.
        }
    }            
}
  

Я хочу очистить некоторый буфер, если это проблема, и сохранить соединение в рабочем состоянии, а запросы отправляются так, как они поступают в течение первых 15 секунд.
Я не уверен, что асинхронность, ожидания и задачи используются правильно.

Спасибо

Комментарии:

1. Сколько запросов вы делаете? Попробуйте создать один экземпляр HttpClient и повторно использовать его вместо того, чтобы создавать и удалять его для каждого запроса. Или попробуйте использовать подобную библиотеку RestSharp , которая не используется HttpClient . Вот интересная статья .

2. However, the setup requires the command being async to be inside a timer — почему? В показанном коде нет ничего, что требовало бы использования таймера. Кроме того, таймер будет срабатывать каждые x мс, независимо от того, выполнен предыдущий вызов или нет. Я бы не стал использовать таймер. Я бы создал асинхронный метод, который принимает токен отмены и зацикливается до тех пор, пока не будет указано отменить. Внутри цикла запустите ваше HTTP-событие, затем дождитесь указанного _updateInterval . Продолжайте, пока не будет запрошена отмена.

3. @ScottHannen пожалуйста, ответьте на мой вопрос, чтобы я мог выбрать в качестве ответа. Ваша статья — ЗОЛОТО! Это сразу же сделало свое дело. Не знал об этом. Очень хорошо сделано и еще раз спасибо.

4. @PatrickTucci тебе не кажется, что если бы я мог избежать таймера, я бы вообще не написал этот комментарий? Вместо того, чтобы писать кучу нерелевантного кода, я изложил факты в комментарии. Это не было проблемой, но таймер необходим. Поверьте мне на слово.

5. github.com/olsh/curl-to-csharp/issues/6

Ответ №1:

Если вы можете выполнять запросы некоторое время, а затем они завершаются сбоем, возможно, вы исчерпали количество доступных сокетов. Это может произойти, когда мы повторно создаем и удаляем an HttpClient для каждого запроса.

Вместо этого мы должны создать HttpClient и использовать его как можно дольше. Технически мы должны избавиться от него, когда закончим с ним, потому что он реализует IDisposable , но мы не закончим с ним до тех пор, пока будем продолжать использовать его повторно. Таким образом, правильный способ его использования и утилизации не ясен на 100%.

В документации говорится:

HttpClient предназначен для создания экземпляра один раз и повторного использования на протяжении всего срока службы приложения. Создание экземпляра класса HttpClient для каждого запроса исчерпает количество доступных сокетов при больших нагрузках. Это приведет к ошибкам SocketException. Ниже приведен пример правильного использования HttpClient.

… и далее следует этот пример:

 public class GoodController : ApiController
{
    // OK
    private static readonly HttpClient HttpClient;

    static GoodController()
    {
        HttpClient = new HttpClient();
    }
}
  

Другой альтернативой является использование чего-то другого, кроме HttpClient . RestSharp не только очень прост в использовании, но и не использует an HttpClient , поэтому вам не нужно беспокоиться о его утилизации. Он обрабатывает много подобных вещей внутри.

Кроме того, вот забавная статья, которая привлекла к этому мое внимание.