C# 异步等待操作奇怪的循环
我有以下客户端侦听器,它将客户端传递给HandleStationClient。HandleStationClient的构造函数使用其他线程中的连接启动一个任务以进行侦听 下面的代码使用异步函数在主线程上运行。当客户端连接时,下面等待的部分将继续,并将客户端传递给新创建的HandleStationClient并钩住事件。 通常情况下,在连接事件后,环路将重新启动,并在等待时等待新的连接。 问题在于,此代码对每个连接循环两次。因此,将创建客户端连接和HandleStationClient,并钩住事件,而循环将再次启动,然后继续运行相同的进程,再次创建新的HandleStationClient和事件钩子 处理完客户端后,等待者不再等待,而是继续第二次。事件被触发两次。我不知道怎么了。有人有线索吗C# 异步等待操作奇怪的循环,c#,wpf,sockets,async-await,C#,Wpf,Sockets,Async Await,我有以下客户端侦听器,它将客户端传递给HandleStationClient。HandleStationClient的构造函数使用其他线程中的连接启动一个任务以进行侦听 下面的代码使用异步函数在主线程上运行。当客户端连接时,下面等待的部分将继续,并将客户端传递给新创建的HandleStationClient并钩住事件。 通常情况下,在连接事件后,环路将重新启动,并在等待时等待新的连接。 问题在于,此代码对每个连接循环两次。因此,将创建客户端连接和HandleStationClient,并钩住事件
while (true)
{
counter += 1;
// Wait for new connection then do rest
stationsClientSocket = await stationsServerSocket.AcceptTcpClientAsync();
stationClients.Add(stationsClientSocket, 0);
Debug.WriteLine("Client toegevoegd " + counter);
HandleStationClients stationClient = new HandleStationClients(stationsClientSocket);
stationClient.ConnectionEstabilished += stationClient_ConnectionEstabilished;
stationClient.ConnectionClosed += stationClient_ConnectionClosed;
stationClient.NewDataReceived += stationClient_NewDataReceived;
}
HandleClient看起来像
class HandleStationClients
{
public HandleStationClients(TcpClient client)
{
Task.Factory.StartNew(() => { ProcessConnection(client); });
}
#region Event definitions
public delegate void NewDataReceivedEventHandler(string newData);
public event NewDataReceivedEventHandler NewDataReceived;
public delegate void ConnectionClosedEventHandler();
public event ConnectionClosedEventHandler ConnectionClosed;
public delegate void ConnectionEstabilishedEventHandler(IPEndPoint endpoint);
public event ConnectionEstabilishedEventHandler ConnectionEstabilished;
#endregion
public async void ProcessConnection(TcpClient stationsClientSocket)
{
byte[] message = new byte[1024];
int bytesRead;
NetworkStream networkStream = stationsClientSocket.GetStream();
if (this.ConnectionEstabilished != null)
{
this.ConnectionEstabilished((IPEndPoint)stationsClientSocket.Client.RemoteEndPoint);
}
while ((true))
{
bytesRead = 0;
try
{
bytesRead = await networkStream.ReadAsync(message, 0, 1024);
}
catch (Exception ex)
{
// some error hapens here catch it
Debug.WriteLine(ex.Message);
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
break;
}
ASCIIEncoding encoder = new ASCIIEncoding();
if (this.NewDataReceived != null)
{
byte[] buffer = null;
string incomingMessage = encoder.GetString(message, 0, bytesRead);
this.NewDataReceived(incomingMessage);
}
}
stationsClientSocket.Close();
// Fire the disconnect Event
this.ConnectionClosed();
}
}
我将任务start从构造函数移到了start方法。问题解决了。在构造函数中启动任务是个坏主意。这意味着您正在注册事件处理程序时任务正在运行。有一个很好的机会,有时你不会得到一个事件注册之前,它需要被解雇 您应该做的是等待启动任务,直到事件处理程序全部注册。您需要创建一个
Start
方法来启动任务,并在事件注册后让代码调用它
更新的类:
class HandleStationClients
{
// Added a field to store the value until the Start method
TcpClient _client;
public HandleStationClients(TcpClient client)
{
this._client = client;
// Moved the line from here...
}
public void Start()
{
// ...to here.
Task.Factory.StartNew(() => { ProcessConnection(_client); });
}
#region Event definitions
// ...
#endregion
public async void ProcessConnection(TcpClient stationsClientSocket)
{
byte[] message = new byte[1024];
int bytesRead;
NetworkStream networkStream = stationsClientSocket.GetStream();
if (this.ConnectionEstabilished != null)
{
this.ConnectionEstabilished((IPEndPoint)stationsClientSocket.Client.RemoteEndPoint);
}
while ((true))
{
bytesRead = 0;
try
{
bytesRead = await networkStream.ReadAsync(message, 0, 1024);
}
catch (Exception ex)
{
// some error hapens here catch it
Debug.WriteLine(ex.Message);
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
break;
}
ASCIIEncoding encoder = new ASCIIEncoding();
if (this.NewDataReceived != null)
{
byte[] buffer = null;
string incomingMessage = encoder.GetString(message, 0, bytesRead);
this.NewDataReceived(incomingMessage);
}
}
stationsClientSocket.Close();
// Fire the disconnect Event
// I added a line to check that ConnectionClosed isn't null
if (this.ConnectionClosed != null)
{
this.ConnectionClosed();
}
}
}
然后您需要按如下所示更改调用代码
while (true)
{
counter += 1;
// Wait for new connection then do rest
stationsClientSocket = await stationsServerSocket.AcceptTcpClientAsync();
stationClients.Add(stationsClientSocket, 0);
Debug.WriteLine("Client toegevoegd " + counter);
HandleStationClients stationClient = new HandleStationClients(stationsClientSocket);
stationClient.ConnectionEstabilished += stationClient_ConnectionEstabilished;
stationClient.ConnectionClosed += stationClient_ConnectionClosed;
stationClient.NewDataReceived += stationClient_NewDataReceived;
// Call Start manually
stationClient.Start();
}
请展示一个简短但完整的程序来演示问题。仅仅从这一小段就想出来发生了什么太难了。我同意乔恩的观点。我试着运行一个短控制台应用程序来实现这一点,但效果很好。我认为将(n个完整的)任务设为异步方法没有多大用处。@Shift,那么您应该自己回答这个问题,或者删除它。