Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 混合使用异步等待和fire and forget方法_C#_Asynchronous_Async Await_Fire And Forget - Fatal编程技术网

C# 混合使用异步等待和fire and forget方法

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

我正在使用.NET的
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