服务器端C#Websocket,如何在侦听取消令牌的同时运行循环? [英] Server-side C# Websocket, how run a loop while listening to the cancellation token?

查看:476
本文介绍了服务器端C#Websocket,如何在侦听取消令牌的同时运行循环?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的Vue/.NET Core 2.3项目中,我已经开始用Websockets替换标准的AJAX调用,在此我实现了股票定价流服务以在股票价格实时更新时更新前端.以前的价格更新用于每隔5秒从FE发送间隔请求,以从方法StockProcess().GetStockPricing(symbol)

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. 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)

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

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.

该实现原则上可以很好地工作,如果价格发生变化,该方法会将更新发送给客户端,完美.

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

Implementation.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循环:

The issue is I cannot cancel the running GetStockPricing loop:

问题在于第WebSocketReceiveResult result = await webSocket.ReceiveAsync(requestBuffer, CancellationToken.None);行未执行,因为循环始终在运行,如果我在循环之前将这行移至要执行的行,则该循环也不会被触发,因此我无法获取循环运行和ReceiveAsync都侦听取消令牌.有没有办法做到这一点?一边听取消标记一边运行循环?

The problem is with line 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. Is there a way to achieve this? running the loop while listening for cancellation tokens?

推荐答案

尝试使用System.Threading.Tasks.Task 运行

try listening for it using a loop inside System.Threading.Tasks.Task Run

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

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

}

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

do this before the webSocket.State loop

这篇关于服务器端C#Websocket,如何在侦听取消令牌的同时运行循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆