#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 тебе не кажется, что если бы я мог избежать таймера, я бы вообще не написал этот комментарий? Вместо того, чтобы писать кучу нерелевантного кода, я изложил факты в комментарии. Это не было проблемой, но таймер необходим. Поверьте мне на слово.
Ответ №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
, поэтому вам не нужно беспокоиться о его утилизации. Он обрабатывает много подобных вещей внутри.
Кроме того, вот забавная статья, которая привлекла к этому мое внимание.