Как отменить HttpListenerContext.AcceptWebSocketAsync?

У него нет параметра маркера отмены. Также HttpListenerContext не имеет связанных методов (Begin/End) AcceptWebSocket.

Ответ 1

Возможно, следующее решение подходит лучше в вашем случае, которое основано на этой статье .

Это прекратит прослушивание, как только маркер отмены будет запущен, тогда вы сможете реализовать пользовательскую логику для отмены операции. В моем случае его достаточно, чтобы разбить цикл, но это действительно может быть что угодно.

    public void Stop()
    {
        this.Status = ServerStatus.Stopping;

        this.listener.Stop();
        this.cancellationTokenSource.Cancel();

        this.Status = ServerStatus.Stopped;
    }

    private async void ListenForConnections(CancellationToken cancellationToken)
    {
        try
        {
            while (this.Status == ServerStatus.Running)
            {
                var socketTask = this.listener.AcceptSocketAsync();

                var tcs = new TaskCompletionSource<bool>();
                using (cancellationToken.Register(s => ((TaskCompletionSource<bool>)s).TrySetResult(true), tcs))
                {
                    if (socketTask != await Task.WhenAny(socketTask, tcs.Task).ConfigureAwait(false))
                        break;
                }

                var context = new TcpContext(socketTask.Result);

                this.OnConnectionReceived(context);
            }
        }
        catch (ObjectDisposedException)
        {
            // Closed
        }
    }

Ответ 2

Хммм, вы получаете контекст от HttpListener, который слушает запросы (контекст не прослушивает сам, он только обходит ваши запросы/ответы, насколько я понимаю). Думаю, вам следует позвонить HttpListener.Stop() Будет ли это трюк?

Ответ 3

Самое лучшее, что вы можете сделать, это обернуть часть прослушивания в потоке и когда вы хотите отменить выполнение Abort в потоке.

Обязательно поймайте ObjectDisposedException, которое может произойти в методе. То же самое для TcpListener более низкого уровня.

    public void Stop()
    {
        this.Status = ServerStatus.Stopping;
        this.listener.Stop();

        this.listeningThread.Abort();

        this.Status = ServerStatus.Stopped;
    }

    /// <summary>
    ///     Listens for connections.
    /// </summary>
    private async void ListenForConnections()
    {
        try
        {
            while (this.Status == ServerStatus.Running)
            {
                var socket = await this.listener.AcceptSocketAsync();
                var context = new TcpContext(socket);

                this.OnConnectionReceived(context);
            }
        }
        catch (ObjectDisposedException)
        {
            // Closed
        }
    }

Ответ 4

Все, что я искал, - это способ убедиться, что AcceptWebSocketAsync не будет зависать вечно, договариваясь с враждебным пультом, который блокирует мои потоки прослушивания. Я новичок в Task и ожидаю /async, но это, кажется, делает то, что я хочу:

CancellationTokenSource upgradeTimeout = new CancellationTokenSource(1000);
HttpListenerWebSocketContext webSocketContext = await Task.Run(async () => { return await httpContext.AcceptWebSocketAsync(null); }, upgradeTimeout.Token);

Что-то не так с этим?

Спасибо