服务器端 C# Websocket,如何在监听取消令牌时运行循环?

Posted

技术标签:

【中文标题】服务器端 C# Websocket,如何在监听取消令牌时运行循环?【英文标题】:Server-side C# Websocket, how run a loop while listening to the cancellation token? 【发布时间】:2019-12-31 07:00:30 【问题描述】:

在我的 Vue/.NET Core 2.3 项目中,我已经开始用 Websockets 替换标准 AJAX 调用,我在其中实施股票定价流服务来更新前端,就像实时更新股票价格一样。之前的价格更新用于每 5 秒从 FE 发送一个间隔请求,以从方法 StockProcess().GetStockPricing(symbol) 获取新价格

下面的新 Websocket 实现现在使用相同的后端 GetStockPricing() 代码,但检查循环现在位于后端,因此当客户端连接时,该方法将继续发送回价格。

原则上实现完美,如果有价格变化,该方法将更新发送给客户端,完美。

APIController.cs

[HttpGet("GetStockPricingAsync", Name = "GetStockPricingAsync")]
public async Task GetStockPricingAsync(string symbol)

    var isSocketRequest = ControllerContext.HttpContext.WebSockets.IsWebSocketRequest;
    if (isSocketRequest)
    
        WebSocket webSocket = await ControllerContext.HttpContext.WebSockets.AcceptWebSocketAsync();
        await _mainController.GetStockPricingAsync(ControllerContext.HttpContext, webSocket, symbol);
    
    else
    
        ControllerContext.HttpContext.Response.StatusCode = 400;
    

实施.cs

public async Task GetStockPricingAsync(HttpContext context, WebSocket webSocket, string symbol)

    var lastUpdated = DateTime.MinValue;
    bool isNotCancelled = true;
    byte[] requestBuffer = new byte[4194304];

    while (webSocket.State == WebSocketState.Open || webSocket.State == WebSocketState.CloseSent)
    
        while (isNotCancelled)
        
            var price = new StockProcess().GetStockPricing(symbol);

            if (lastUpdated != price.LastPriceDate)
            
                lastUpdated = price.LastPriceDate;
                var json = JsonConvert.SerializeObject(new ServerData(price, _eventMessage), _jsonSerializerSettings);
                requestBuffer = Encoding.ASCII.GetBytes(json);
                var arraySegment = new ArraySegment<byte>(requestBuffer);
                await webSocket.SendAsync(arraySegment, WebSocketMessageType.Text, true, CancellationToken.None);
            
            Thread.Sleep(300);
        
        WebSocketReceiveResult result = await webSocket.ReceiveAsync(requestBuffer, CancellationToken.None);

        if (result.MessageType == WebSocketMessageType.Close)
        
            isNotCancelled = false
            await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
            break;
        
    

问题是我无法取消正在运行的GetStockPricing 循环:

问题在于WebSocketReceiveResult result = await webSocket.ReceiveAsync(requestBuffer, CancellationToken.None); 行没有被执行,因为循环一直在运行,如果我将此行移到循环之前执行,那么循环也不会被触发,所以我无法得到循环运行和 ReceiveAsync 都在监听取消令牌。有没有办法做到这一点?在监听取消令牌的同时运行循环?

【问题讨论】:

【参考方案1】:

尝试使用 System.Threading.Tasks.Task 中的循环监听它Run

Task.Run(() => CancellationTokenFunc(...), ...);

static void CancellationTokenFunc()
  while(true)
             //check for cancel
    


在 webSocket.State 循环之前执行此操作

【讨论】:

我之前做过,并与 CancellationTokenSource 合作过,想更新我自己的答案,但你打败了我,谢谢你的努力,我会接受你的

以上是关于服务器端 C# Websocket,如何在监听取消令牌时运行循环?的主要内容,如果未能解决你的问题,请参考以下文章

如何让 C# WebSocketClient 持续监听消息

c# webapi websocket 服务端消息发送

如何使用 node.js“ws”库服务器端监听后续消息

C# WebSocket 服务端示例代码 + HTML5客户端示例代码

微信小程序webSocket多人通信案例

C#解惑3——WebSocket与消息推送(转)