我有一些通过各种事件“链接”的类。基本上是TCPListener
,ClientSession
和Server
。
将TCPListener
新连接冒泡到Server
,然后Server
创建一个新的ClientSession
。
TCPListener
通过事件传递新的套接字ClientConnected
。
引发事件的方法如下所示:
//Processes a new connection and immediately puts the listen socket back in a receiving state
private void ProcessAccept(SocketAsyncEventArgs e)
{
ClientConnected(this, e));
StartAccept();
}
我想避免做任何可能阻止或减慢对新客户的接受的事情,所以我努力通过Task来引发这一事件。这样做的原因是,用户可以覆盖该OnClientConnected
方法,Server
以使其长时间运行并可能影响服务器性能。
这是修改后的方法:
//Processes a new connection and immediately puts the listen socket back in a receiving state
private void ProcessAccept(SocketAsyncEventArgs e)
{
Task.Run(() => ClientConnected(this, e));
StartAccept();
}
当使用新方法运行程序时,崩溃不会发生任何异常,但是服务器无法接收或发送给客户端。
这是中的OnClientConnected
方法Server
:
/// <summary>
/// An event that is fired when a client connects.
/// </summary>
/// <param name="sender">The Listener that accepted the connection</param>
/// <param name="e">The SocketAsyncEventArgs </param>
protected virtual void OnClientConnected(object sender, EventArgs e)
{
ClientSession Session = ClientSessionPool.Pop();
Session.Socket = ((SocketAsyncEventArgs)e).AcceptSocket;
string WelcomeMessage = "Connected";
Session.SendAsync(Encoding.Default.GetBytes(WelcomeMessage));
this.ClientSessions.Add(Session);
Console.Write($"\rConnected clients:{ClientSessions.Count}");
}
只需恢复到旧的同步方法就可以了。
让我感到烦恼的是,SocketAsyncEventArgs
无论是否使用,通过事件传递的似乎都是正确的Task
,这是我能想到的唯一失败点。
SocketAsyncEventArgs
使用Task
该方法的版本时,似乎是完全错误的。
我怀疑这是我对分配给新线程的堆栈的理解,这引起了我的困惑。谁能看到我的逻辑上的漏洞?谢谢!
聚苯乙烯
我知道我当前的ClientSessions
列表实现不是线程安全的,但是在我的测试中,我一次只能与一个客户端建立连接。我最终将解决该问题。
PPS这是在StartAccept
有用的情况下的方法:
//Puts the accepting TCP socket back into an accepting state
public void StartAccept()
{
// socket must be cleared since the context object is being reused
m_SocketEventArgs.AcceptSocket = null;
bool willRaiseEvent = m_Socket.AcceptAsync(m_SocketEventArgs);
if (!willRaiseEvent)
{
ProcessAccept(m_SocketEventArgs);
}
}
解决方案是在UI线程上引发事件,但异步运行事件处理。
private async void OnClientConnected(object sender, EventArgs e)
{
await Task.Run(() => HandleClientConnected(object, e));
}
protected abstract Task HandleClientConnected(object sender, EventArgs e);
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句