Windows服务线程没有在c#中及时停止

时间:2014-02-27 11:22:36

标签: c# multithreading windows-services

我有一个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
    }
}

}

请帮我解决这个问题。

4 个答案:

答案 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);上使用了超时。这使线程有机会进行干净关闭,然后继续。