Mixing async-await with fire-and-forget approach
我正在使用.NET的
本质上,我有一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | private async void HandleListener() { try { while (listener != null && listener.IsListening) { HttpListenerContext listenerContext = await listener.GetContextAsync(); WebSocketContext webSocketContext = await listenerContext.AcceptWebSocketAsync(subProtocol: null); WebSocket webSocket = webSocketContext.WebSocket; clients.Add(webSocket); await HandleClient(webSocket); } } catch (HttpListenerException) { } // Got here probably because StopWSServer() was called } private async Task HandleClient(WebSocket client) { ... } |
问题是,我似乎无法处理一个以上的客户。 只要连接了第一个客户端,
我尝试从对
顺便说一句,
1 | recieveResult = await client.ReceiveAsync(recievedBuffer, CancellationToken.None); |
据我了解,一劳永逸的做法总体上是不好的,而且我似乎无法通过async-await实现来实现。 但是
编辑:添加了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | private async Task HandleClient(WebSocket client) { try { ArraySegment<byte> recievedBuffer = new ArraySegment<byte>(new byte[BUFFER_SIZE]); while (listener != null && listener.IsListening && client.State == WebSocketState.Open) { WebSocketReceiveResult recieveResult; using (var ms = new MemoryStream()) { do { recieveResult = await client.ReceiveAsync(recievedBuffer, CancellationToken.None); ms.Write(recievedBuffer.Array, recievedBuffer.Offset, recieveResult.Count); } while (!recieveResult.EndOfMessage); switch (recieveResult.MessageType) { case WebSocketMessageType.Close: RemoveClient(client, WebSocketCloseStatus.NormalClosure, string.Empty); break; case WebSocketMessageType.Binary: RemoveClient(client, WebSocketCloseStatus.InvalidMessageType,"Cannot accept binary frame"); break; case WebSocketMessageType.Text: OnRecieve?.Invoke(client, System.Text.Encoding.UTF8.GetString(ms.ToArray())); break; } } } } catch (WebSocketException ex) { RemoveClient(client, WebSocketCloseStatus.InternalServerError, ex.Message); } } |
为了防止编译器警告,请使用如下方法:
1 2 3 4 5 | public static class TaskExtensions { public static void Forget(this Task task) { } } |
然后做
1 | HandleClient(webSocket).Forget() |
如果走这条路,请确保以某种方式处理
替代方法是:
1 2 3 4 5 | HandleClient(webSocket).ContinueWith(task => { if (task.IsFaulted && task.Exception != null) { // handle it here } }); |
如您所见,在这种情况下,等待
之所以会这样,是因为您为此编写了代码,我的意思是说您编写了如下方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | private async void HandleListener() { try { while (listener != null && listener.IsListening) { HttpListenerContext listenerContext = await listener.GetContextAsync(); WebSocketContext webSocketContext = await listenerContext.AcceptWebSocketAsync(subProtocol: null); WebSocket webSocket = webSocketContext.WebSocket; clients.Add(webSocket); await HandleClient(webSocket); } } catch (HttpListenerException) { } // Got here probably because StopWSServer() was called } |
在此方法中,当遇到
检查下面的图片,这如何等待和异步工作
如果你只是想生火而忘了尝试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | private void HandleListener() { try { while (listener != null && listener.IsListening) { HttpListenerContext listenerContext = await listener.GetContextAsync(); WebSocketContext webSocketContext = await listenerContext.AcceptWebSocketAsync(subProtocol: null); WebSocket webSocket = webSocketContext.WebSocket; clients.Add(webSocket); HandleClient(webSocket); } } catch (HttpListenerException) { } // Got here probably because StopWSServer() was called } |
这意味着不要等待任务完成