У нас есть несколько клиентов, которые подключаются к серверу по именованным каналам. Иногда мы видим ошибку pipe/file not found
, когда клиент пытается подключиться к именованному каналу. Наш оригинальный код
while (!cancelToken.IsCancellationRequested)
{
// This creates a new NamedPipeServerStream
var stream = PipeHelper.NewCurrentUserServerStream(PipeNames.Server, PipeTransmissionMode.Byte);
await stream.WaitForConnectionAsync(cancelToken);
Task.Run(() => HandleStreamAsync(stream).WithExceptionTrapper(LogNamedPipeException));
Из того, что я могу сказать, следует создать NamedPipeServerStream
и затем вызвать WaitForConnection
, тогда сервер должен обработать запрос.
Однако, если этот запрос близок к мгновенному, или клиент закрывает канал, представляется вероятным, что поток сервера будет закрыт, а весь именованный канал исчезнет, прежде чем код зацикливается и создается новый поток сервера. .
Итак, как мы можем гарантировать, что именованный канал существует на протяжении всего срока службы сервера, независимо от времени и количества подключающихся клиентов?
Код здесь https://docs.microsoft.com/en-us/dotnet/standard/io/how-to-use-named-pipes-for-network-interprocess-communication предполагает, что просто использовать несколько потоков - вариант (4, в этом примере). Однако, похоже, это только уменьшает вероятность ошибки, и клиент может попытаться подключиться в редком промежутке, когда все 4 потока только что закрыли поток сервера, и именованный канал исчезает. Кроме того, он ограничивает параллельное выполнение до 4 потоков.
Существует ли механизм, позволяющий нам открывать именованный сервер каналов, который допускает произвольное количество соединений, создает новый поток сервера для каждого соединения и никогда не рискует закрыть именованный канал?
Прямо сейчас мы думаем сделать это:
var nextStream = PipeHelper.NewCurrentUserServerStream(PipeNames.Server, PipeTransmissionMode.Byte);
while (!cancelToken.IsCancellationRequested)
{
try
{
await nextStream.WaitForConnectionAsync(cancelToken);
var currentStream = nextStream;
// Always have another stream ready so if the task is handled and finished
// really quickly theres no chance of the named pipe being removed altogether.
nextStream = PipeHelper.NewCurrentUserServerStream(PipeNames.Server, PipeTransmissionMode.Byte);
Task.Run(() => HandleStreamAsync(currentStream).WithExceptionTrapper(LogNamedPipeException));
}
Это в основном гарантирует, что мы создадим второй поток сервера, прежде чем мы начнем обрабатывать соединение с первым потоком сервера, поэтому мы гарантируем, что всегда есть один активный, и мы запускаем обработчик для отдельной задачи, поэтому мы должны запустить другой WaitForConnection как можно скорее.
Существует ли шаблон структуры, который позволяет нам выполнять вышеизложенное, поддерживая любое количество параллельных клиентов и гарантируя, что именованный канал никогда не будет удален, если сервер все еще активен?