C# 关于重置事件和线程,此tcp侦听器代码是否正确实现?
我有这个代码,我觉得它工作得不好。我已经把它拼凑在一起,它可以工作,但我不完全理解异步线程和ResetEvents 当我用一个多线程客户端测试这个监听器时,响应时间从最初10秒左右的300毫秒到最后50秒的2-3秒 1.)线程和resetevent处理程序是否按照设计的方式实现 2.)是否有办法加快高流量突发的响应时间 3.)在另一个线程上运行tcpConnectionLogic有意义吗 我有一个全局范围的手动和自动重置事件:C# 关于重置事件和线程,此tcp侦听器代码是否正确实现?,c#,multithreading,tcp,windows-services,C#,Multithreading,Tcp,Windows Services,我有这个代码,我觉得它工作得不好。我已经把它拼凑在一起,它可以工作,但我不完全理解异步线程和ResetEvents 当我用一个多线程客户端测试这个监听器时,响应时间从最初10秒左右的300毫秒到最后50秒的2-3秒 1.)线程和resetevent处理程序是否按照设计的方式实现 2.)是否有办法加快高流量突发的响应时间 3.)在另一个线程上运行tcpConnectionLogic有意义吗 我有一个全局范围的手动和自动重置事件: private AutoResetEvent connecti
private AutoResetEvent connectionWaitHandle = new AutoResetEvent(false);
private ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
我有一个windows服务,它在新线程上启动tcp侦听器
protected override void OnStart(string[] args)
{
_mainThread = new Thread(ThreadListener_Begin);
_mainThread.Name = "EMServiceThread";
_mainThread.IsBackground = false;
_mainThread.Start();
}
我的线程运行一个循环,等待手动重新发送事件发出关机信号
private void ThreadListener_Begin()
{
TcpListener listener = null;
listener = new TcpListener(IPAddress.Parse("172.16.30.248"), 10010);
listener.ExclusiveAddressUse = false;
listener.Start();
while (!_shutdownEvent.WaitOne(0))
{
IAsyncResult result = listener.BeginAcceptTcpClient(HandleAsyncConnection, listener);
connectionWaitHandle.WaitOne();
}
}
最后,当连接进来时,我接受它并将其传递给一种逻辑层,该逻辑层处理请求
private void HandleAsyncConnection(IAsyncResult result)
{
TcpListener listener = (TcpListener)result.AsyncState;
connectionWaitHandle.Set();
TcpClient c = listener.EndAcceptTcpClient(result);
var _tcpConnectedLogic = new TcpConnectionLogic(c);
_tcpConnectedLogic.BadRequestAlert += _serviceLogic_BadRequestAlert;
_tcpConnectedLogic.RequestDecodedAlert += _tcpConnectedLogic_RequestDecodedAlert;
_tcpConnectedLogic.Start();
}
编辑
当我停止服务时,我的线程并没有像我期望的那样关闭。而是以流产告终。为什么?我怎样才能使它优雅地靠近
protected override void OnStop()
{
WriteToEventLog("Stop Command Received" + CurrentTimeStamp, entryType: EventLogEntryType.Information);
WriteToLogFile("Stop Command Received @ " + CurrentTimeStamp);
_shutdownEvent.Set();
if (!_mainThread.Join(4000))
{
WriteToEventLog("OnStop: Aborting thread, Join did not work. This is not preferred.", entryType: EventLogEntryType.Warning);
_mainThread.Abort();
}
}
在这个街区
while (!_shutdownEvent.WaitOne(0))
{
IAsyncResult result = listener.BeginAcceptTcpClient(HandleAsyncConnection, listener);
connectionWaitHandle.WaitOne();
}
您基本上是在循环中接受客户机,因为您通过等待connectionWaitHandle阻塞线程。您也可以忘记异步内容,只需执行以下操作:
while (!_shutdownEvent.WaitOne(0))
{
var client = listener.AcceptTcpClient();
// start your logic in separate thread
}
我并不是说您应该这样做,只是要注意,您当前的“异步”实现并没有比同步实现增加任何好处
然后,由于connectionWaitHandle上的相同阻塞,您在中止线程方面遇到了问题。例如,假设您刚刚启动了侦听器,但没有连接任何客户端。然后,客户端在connectionWaitHandle上被阻塞,而您设置的_shutdownEvent对这一事实没有帮助-主线程将永远没有机会检查它
解决此问题的最佳选择是使用基于任务的方法:
class Listener {
// we don't use cancellation tokens because AcceptTcpClientAsync does not support them anyway
private volatile bool _shutdown;
private TcpListener _listener;
public async Task Start() {
_listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 10010);
_listener.ExclusiveAddressUse = false;
_listener.Start();
while (!_shutdown) {
TcpClient client = null;
try {
client = await _listener.AcceptTcpClientAsync();
}
catch (ObjectDisposedException) {
// will be thrown when you stop listener
}
if (client != null) {
var tcpConnectedLogic = new TcpConnectionLogic(client);
// start processing on thread pool thread if necessary
// don't wait for it to finish - you need to accept more connections
tcpConnectedLogic.StartAsync();
}
}
}
public void Stop() {
_shutdown = true;
_listener.Stop();
}
}
使用async\await可以吗?响应时间问题必须来自此处不可见的代码。发布请求处理代码。@usr您是否建议我显示的代码正确实现?它有质量问题(请参见答案),但不应表现出特定的行为(高延迟)。MSDN示例令人讨厌。看看为什么这没有意义的答案。这不难理解。编写MSDN套接字代码的人不知道他做了什么。我如何实现tcpConnectedLogic.StartAsync()?我不明白你为什么说connectionWaitHandle不工作。代码应该等待等待,直到设置了等待句柄——这发生在新线程上的所有处理开始之前。因此,在收到客户机之后,我的理解是主线程继续循环,而之前的连接在新线程中继续,代码在我的逻辑层中。1。只要在线程池线程(Task.run(YourLogic))上运行所有逻辑即可。您最好在单独的线程上运行它,因为这样您就可以同时接受更多的连接。否则,在接受下一个客户端之前,您必须先处理一个客户端。connectionWaitHandle确实可以工作——但这样,您就可以通过等待该句柄来阻塞主线程,从而同步地接受连接。异步接受连接的要点是,等待不会阻塞任何线程。另外,您这样做会导致线程中止问题,如答案中所述。我正在尝试修改代码,但它不配合。谢谢你的提示,我会继续尝试,但暂时不行。