设为首页 加入收藏

TOP

TaskCreationOptions.LongRunning 运行比可用线程数更多的任务(一)
2019-09-17 19:08:25 】 浏览:90
Tags:TaskCreationOptions.LongRunning 运行 可用 线程 更多 任务


最近在学WebSocket,服务端需要监听多个WebSocket客户端发送的消息。

开始的解决方法是每个WebSocket客户端都添加一个线程进行监听,代码如下:

/// <summary>
/// 监听端口 创建WebSocket
/// </summary>
/// <param name="httpListener"></param>
private void CreateWebSocket(HttpListener httpListener)
{
    if (!httpListener.IsListening)
        throw new Exception("HttpListener未启动");
    HttpListenerContext listenerContext =  httpListener.GetContextAsync().Result;

    if (!listenerContext.Request.IsWebSocketRequest)
    {
        CreateWebSocket(httpListener);
        return;
    }

    WebSocketContext webSocket = null;
    try
    {
        webSocket = new WebSocketContext(listenerContext, SubProtocol);
    }
    catch (Exception ex)
    {
        log.Error(ex);
        CreateWebSocket(HttpListener);
        return;
    }

    log.Info($"成功创建WebSocket:{webSocket.ID}");

    int workerThreads = 0, completionPortThreads = 0;
    ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);
    if (workerThreads <= ReservedThreadsCount + 1 || completionPortThreads <= ReservedThreadsCount + 1)
    {
        /**
         * 可用线程小于预留线程数量
         * 通知客户端关闭连接
         * */
        webSocket.CloseAsync(WebSocketCloseStatus.InternalServerError, "可用线程不足,无法连接").Wait();
    }
    else
    {
        if (OnReceiveMessage != null)
            webSocket.OnReceiveMessage += OnReceiveMessage;
        webSocket.OnCloseWebSocket += WebSocket_OnCloseWebSocket;
        webSocketContexts.Add(webSocket);

        // 在线程中监听客户端发送的消息
        ThreadPool.QueueUserWorkItem(new WaitCallback(p =>
        {
            (p as WebSocketContext).ReceiveMessageAsync().Wait();
        }), webSocket);

    }

    CreateWebSocket(HttpListener);
}
在线程中添加监听代码

 

但是可用线程数量是有限的,先连接的客户端一直递归接收消息,导致线程无限占用,后连接上的客户端就没有线程用于监听接受消息了。
接受消息方法如下:

/// <summary>
/// 递归 同步接收消息
/// </summary>
/// <returns></returns>
public void ReceiveMessage()
{
    WebSocket webSocket = HttpListenerWebSocketContext.WebSocket;

    if (webSocket.State != WebSocketState.Open)
        throw new Exception("Http未握手成功,不能接受消息!");
    
    var byteBuffer = WebSocket.CreateServerBuffer(ReceiveBufferSize);
    WebSocketReceiveResult receiveResult = null;
    try
    {
        receiveResult = webSocket.ReceiveAsync(byteBuffer, cancellationToken).Result;
    }
    catch (WebSocketException ex)
    {
        if (ex.InnerException is HttpListenerException)
        {
            log.Error(ex);
            CloseAsync(WebSocketCloseStatus.ProtocolError, "客户端断开连接" + ex.Message).Wait(TimeSpan.FromSeconds(20));
            return;
        }
        else
        {
            log.Error(ex);
            CloseAsync(WebSocketCloseStatus.ProtocolError, "WebSocket 连接异常" + ex.Message).Wait(TimeSpan.FromSeconds(20));
            return;
        }
    }
    catch (Exception ex)
    {
        log.Error(ex);
        CloseAsync(WebSocketCloseStatus.ProtocolError, "客户端断开连接" + ex.Message).Wait(TimeSpan.FromSeconds(20));
        return;
    }
    if (receiveResult.CloseStatus.HasValue)
    {
        log.Info("接受到关闭消息!");
        CloseAsync(receiveResult.CloseStatus.Value, receiveResult.CloseStatusDescription).Wait(TimeSpan.FromSeconds(20));
        return;
    }

    byte[] bytes = new byte[receiveResult.Count];
    Array.Copy(byteBuffer.Array, bytes, bytes.Length);

    string message = Encoding.GetString(bytes);
    log.Info($"{ID}接收到消息:{message}");

    if (OnReceiveMessage !=
首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇.net core入门-发布及部署_异常(.. 下一篇9.10 翻译系列:EF数据注解特性之..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目