Search code examples
.netwebsockettask-parallel-libraryasyncsocketcancellationtokensource

Cancel a .Net WebSocket SendAsync Immediately


I am using websocket to send out message to 1000 clients. I want to cancel the websocket.SendAsync if the message was not sent out within 100 ms. My code is below.

var cancelTaskToken = transport.GetTaskCancelToken();
        cancelTaskToken.CancelAfter(100);
        var webSocket = transport.GetWebSocket().WebSocket;



        var webSocketContext = new WebSocketSendContext(webSocket, message.Value, transport, Counters, _trace);
        var context = (WebSocketSendContext)webSocketContext;
        try
        {
            if (context.socket.State != System.Net.WebSockets.WebSocketState.Open) return;
            await context.socket.SendAsync(context.payload, System.Net.WebSockets.WebSocketMessageType.Binary, true, cancelTaskToken.Token);
            context.transport.MarkHeatBeat();
            context.counters.MessagesSentToClientTotal.Increment();
            context.counters.MessagesSentToClientPerSec.Increment();

        }
        catch (OperationCanceledException ex)
        {
            context.trace.Error(ex, "cancel socket sending on {connectionId}. websocket state: {webSocketState}", transport.ConnectionId, webSocket.State);
            context.counters.ErrorsTransportPerSec.Increment();
            context.counters.ErrorsTransportTotal.Increment();
            context.counters.ErrorsAllPerSec.Increment();
            context.counters.ErrorsAllTotal.Increment();
        }

But in my test, the sendAsync always cacel after 1000 ms. I don't know why websocket doesn't pick up my 100ms setting?

I use serilog/seq to trace my application. Here are the trace image enter image description here


Solution

  • @SeanOB, you are right. The 1 sec gap in the log is the serilog logging internal. It is not then canceling timeout setting in my CancelToken.

    I now can confirm that the cancel did happen after 100ms.