简体   繁体   English

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

[英]Server-side C# Websocket, how run a loop while listening to the cancellation token?

In my Vue/.NET Core 2.3 project I have started replacing standard AJAX calls with Websockets where I'm implementing a Stock pricing streaming service to update the front end as when stock prices get updated in real time.在我的 Vue/.NET Core 2.3 项目中,我已经开始用 Websockets 替换标准 AJAX 调用,我正在实施股票定价流服务来更新前端,就像股票价格实时更新一样。 The previous price update used to send a interval request from the FE every 5 seconds to get the new prices from method StockProcess().GetStockPricing(symbol)先前的价格更新用于每 5 秒从 FE 发送一个间隔请求,以从方法StockProcess().GetStockPricing(symbol)获取新价格

The new Websocket implementation below is now using the same backend GetStockPricing() code however the check loop now is in the back end, so while client is connected the method will keep sending prices back.下面的新 Websocket 实现现在使用相同的后端 GetStockPricing() 代码,但是检查循环现在位于后端,因此当客户端连接时,该方法将继续发送回价格。

The implementation works fine perfectly as a principle, if there is a price change, the method will send the update to the client, perfect.原则上该实现完美无缺,如果价格发生变化,该方法会将更新发送给客户端,完美。

APIController.cs 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;
    }
}

Implementation.cs实现.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;
        }
    }
}

The issue is I cannot cancel the running GetStockPricing loop:问题是我无法取消正在运行的GetStockPricing循环:

The problem is with line WebSocketReceiveResult result = await webSocket.ReceiveAsync(requestBuffer, CancellationToken.None);问题在于行WebSocketReceiveResult result = await webSocket.ReceiveAsync(requestBuffer, CancellationToken.None); does not get executed since the loop is always running, if I move this line to be executed before the loop then the loop does not get triggered as well, so I'm unable to get both loop running and ReceiveAsync listening for a cancellation token.由于循环始终在运行,因此不会执行,如果我将此行移到循环之前执行,则循环也不会被触发,因此我无法同时运行循环和 ReceiveAsync 侦听取消令牌。 Is there a way to achieve this?有没有办法做到这一点? running the loop while listening for cancellation tokens?在侦听取消令牌时运行循环?

try listening for it using a loop inside System.Threading.Tasks.Task Run尝试使用 System.Threading.Tasks.Task Run中的循环来监听它

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

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

}

do this before the webSocket.State loop在 webSocket.State 循环之前执行此操作

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM