我有一个Windows服务,它开始使用Thread.After安装后作为Windows服务我能够正常启动服务,但一旦我尝试停止服务,它需要花费太多时间,而不是停止。我使用ManualResetEvent
来停止Windows服务这是我的代码。
protected override void OnStart(string[] args)
{
_thread = new Thread(DoWork);
_thread.Start();
}
private void DoWork()
{
while (!_shutdownEvent.WaitOne(0))
{
data = new byte[1024];
int recv = sock.Receive(data);
stringData = Encoding.ASCII.GetString(data, 0, recv);
}
sock.Shutdown(SocketShutdown.Both);
sock.Close();
}
catch (Exception DFGFD)
{
}
}
protected override void OnStop()
{
_shutdownEvent.Set();
_thread.Join(); // wait for thread to stop
}
}
}
请帮我解决这个问题。
答案 0 :(得分:1)
您的套接字阻止了接收代码。我建议发出:
sock.Shutdown(SocketShutdown.Both);
sock.Close();
在从OnStop()
处理程序调用的方法中(因此从另一个线程调用阻塞Receive
)。这将导致阻塞sock.Receive
失败,并且您可以通过退出循环来处理该异常。
答案 1 :(得分:0)
可能while
中的代码阻塞(即同步等待来自连接的数据)
通常,您应该对套接字使用异步I / O操作,这通常允许您避免启动新线程。
答案 2 :(得分:0)
问题在于循环中对Receive的调用。来自MSDN:
如果没有可用于读取的数据,则Receive方法将被阻止 直到数据可用,除非使用设置了超时值 Socket.ReceiveTimeout。如果超出超时值,则接收 call会抛出一个SocketException。如果您处于非阻塞模式, 并且协议栈缓冲区中没有可用的数据, Receive方法将立即完成并抛出一个 SocketException。您可以使用Available属性来确定是否 数据可供阅读。当Available为非零时,重试 接受手术。
因此,我建议将循环中的代码更改为:
if (sock.Available > 0)
{
data = new byte[1024];
int recv = sock.Receive(data);
stringData = Encoding.ASCII.GetString(data, 0, recv);
}
Thread.Sleep(200);
此代码检查数据是否可用于读取,仅在有数据要读取时调用Receive。为了避免忙碌等待,它会发出一个调用Thread.Sleep。
如果要避免调用Thread.Sleep,可以在套接字上指定ReceiveTimeout:
sock.ReceiveTimeout = 200;
while
循环中的代码如下所示:
try
{
data = new byte[1024];
int recv = sock.Receive(data);
stringData = Encoding.ASCII.GetString(data, 0, recv);
}
catch(SocketException ex)
{
if (ex.SocketErrorCode != SocketError.TimedOut)
throw;
// In case of Timeout, do nothing, continue loop
}
答案 3 :(得分:0)
问题: Receive()正在等待其他输入。
Thread.Join()
函数正在等待线程完成。
可能的解决方案:
当我遇到类似情况时,我在Join函数thread.Join(3000);
上使用了超时。这使线程有机会进行干净关闭,然后继续。