C# 混合使用异步等待和fire and forget方法
我正在使用.NET的C# 混合使用异步等待和fire and forget方法,c#,asynchronous,async-await,fire-and-forget,C#,Asynchronous,Async Await,Fire And Forget,我正在使用.NET的HttpListener类编写websocket服务器 本质上,我有一个HandleListener()函数,它等待客户端连接并将每个客户端发送到HandleClient(WebSocket客户端)。所以我现在有: private async void HandleListener() { try { while (listener != null && listener.IsListen
HttpListener
类编写websocket服务器
本质上,我有一个HandleListener()
函数,它等待客户端连接并将每个客户端发送到HandleClient(WebSocket客户端)
。所以我现在有:
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) { ... }
问题是,我似乎不能处理超过一个客户。只要连接了第一个客户端,HandleListener()
的执行就会停止
我试图从调用HandleClient()
中删除wait
,但我得到了“因为此调用未被等待…”错误。我可以使HandleClient()
成为async void
方法,但这不是事件处理程序。顺便说一句,
HandleClient()
之所以是async Task
,是因为它在循环中运行,直到侦听器死机:
recieveResult = await client.ReceiveAsync(recievedBuffer, CancellationToken.None);
据我所知,fire-and-forget方法总体上是不好的,我似乎无法通过异步等待实现来实现它。但是,HandleClient()
是一种“一劳永逸”的方法,我看不到任何其他方法可以满足我的需要
编辑:添加了当前实现的
HandleClient()
:
专用异步任务HandleClient(WebSocket客户端)
{
尝试
{
ArraySegment ReceivedBuffer=新的ArraySegment(新字节[缓冲区大小]);
while(listener!=null&&listener.IsListening&&client.State==WebSocketState.Open)
{
WebSocketReceiveResult接收结果;
使用(var ms=new MemoryStream())
{
做
{
ReceiveResult=Wait client.ReceiveAsync(ReceivedBuffer,CancellationToken.None);
ms.Write(receivedbuffer.Array,receivedbuffer.Offset,receiveResult.Count);
}
而(!receiveResult.EndOfMessage);
开关(ReceiveResult.MessageType)
{
案例WebSocketMessageType。关闭:
RemoveClient(客户端,WebSocketCloseStatus.NormalClose,string.Empty);
打破
案例WebSocketMessageType.Binary:
RemoveClient(客户端,WebSocketCloseStatus.InvalidMessageType,“无法接受二进制帧”);
打破
案例WebSocketMessageType。文本:
onreceive?.Invoke(客户端,System.Text.Encoding.UTF8.GetString(ms.ToArray());
打破
}
}
}
}
捕获(WebSocketException例外)
{
RemoveClient(客户端,WebSocketCloseStatus.InternalServerError,ex.Message);
}
}
它会这样做,因为您为它编写了代码,我的意思是您编写的方法如下
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
}
在这个方法中,当它遇到await
控件时,它将返回到原始调用者,直到您等待部分完成并在它之后开始下一个调用
查看下图,了解wait和async是如何工作的
如果你只是想要火而忘记,那就试试这样吧
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
}
这意味着不要等待任务完成,它会这样做,因为你为它编写了代码,我的意思是你编写了如下方法
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
}
在这个方法中,当它遇到await
控件时,它将返回到原始调用者,直到您等待部分完成并在它之后开始下一个调用
查看下图,了解wait和async是如何工作的
如果你只是想要火而忘记,那就试试这样吧
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
}
这意味着不要等待任务完成要防止编译器发出警告,请使用以下方法:
public static class TaskExtensions {
public static void Forget(this Task task) {
}
}
那就做吧
HandleClient(webSocket).Forget()
如果您这样做,请确保以某种方式处理HandleClient
中的所有异常(例如,将整个过程包装到try-catch中)。在这种特殊情况下,这种方法没有本质上的“坏”
替代办法是:
HandleClient(webSocket).ContinueWith(task => {
if (task.IsFaulted && task.Exception != null) {
// handle it here
}
});
在这种情况下,等待
HandleClient
不是一个选项,正如您自己所见。要防止编译器警告,请使用以下方法:
public static class TaskExtensions {
public static void Forget(this Task task) {
}
}
那就做吧
HandleClient(webSocket).Forget()
如果您这样做,请确保以某种方式处理HandleClient
中的所有异常(例如,将整个过程包装到try-catch中)。在这种特殊情况下,这种方法没有本质上的“坏”
替代办法是:
HandleClient(webSocket).ContinueWith(task => {
if (task.IsFaulted && task.Exception != null) {
// handle it here
}
});
在这种情况下,等待
HandleClient
不是一个选项,正如您自己所看到的。HandleClient做什么?你说这是火和忘记。但为什么它是异步的呢?它是异步的,因为它在一个循环中等待client.ReceiveAsync…。我编辑了这个问题,把它包括进去。但这不是“火与忘”。当你等待接收完成时,你没有忘记。问题似乎出在代码的结构上。HandleClient
中的一行内容不足以帮助解决这个问题。我添加了HandleClient()
实现。HandleClient
做什么?你说这是火和忘记。但为什么它是异步的呢?它是异步的,因为它在一个循环中等待client.ReceiveAsync…。我编辑了这个问题,把它包括进去。但这不是“火与忘”。当你等待接收完成时,你没有忘记。问题似乎出在代码的结构上。HandleClient
中的一行内容不足以帮助解决这个问题。我添加了HandleClient()
实现。这是一种高风险的方法。你不知道HandleClient
本身是否是async
以及它的功能。事实上,HandleClient
是async
@Sefe-你知道,但他想要开火,忘记我写这篇文章的原因code@galah92-在那c