Тайм-ауты при асинхронном соединении через сокет с SocketAsyncEventArgs - PullRequest
4 голосов
/ 16 февраля 2012

Я использую SocketAsyncEventArgs для связи с сотнями устройств (большинство из них через GPRS). Иногда некоторые из них перестают отвечать, и кажется, что у меня нет способа тайм-аута операции, поскольку в документации указано, что параметры тайм-аута (например, SocketOptionName.SendTimeout ) не работают при асинхронной связи. *

Я ищу способ проверки таймаутов при выполнении Send / Receive / ConnectAsync. Он не должен блокировать поток (поэтому вызов someMonitor.WaitOne (SomeTimeoutValue) не будет выполняться), и я не хочу создавать экземпляр таймера для каждой операции (так как количество устройств наверняка увеличится).

Какие-нибудь советы по этому поводу?

1 Ответ

2 голосов
/ 17 февраля 2012

Вот как я это сделал (хотя мне не понравилось решение):

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

public interface ITimeoutable {
    event Action<ITimeoutable, Operation> Begin;
    event Action<ITimeoutable, Operation> End;
    void DoTimeout(Operation operation);
}

, где Operation - это enum, определяемый как:

public enum Operation {
    Connect,
    Send,
    Receive,
    Disconnect
}

, поэтому клиент вызывает событие Begin при запускеасинхронная операция и вызывает событие End по завершении.С другой стороны, я создал TimeoutManager, в котором есть коллекция асинхронных клиентов и словарь с операциями и моментом их запуска.Когда создается новый клиент, он регистрируется в TimeoutManager, который подписывается на события.TimeoutManager использует System.Threading.Timer для проверки тайм-аута операций.Если время ожидания истекло, вызывается метод DoTimeout (из интерфейса ITimeoutable).

Это довольно сложный код, и он мне не нравится.Но это работает.

...