简体   繁体   English

Windows Service中托管的WCF服务停止挂起

[英]WCF Service hosted in Windows Service hangs on stop

I have a WCF Service hosted in a Windows service as described here . 我在Windows服务中托管了WCF服务, 如此处所述 I have scheduled nightly restart of the service, but sometimes the restart fails and the service remains/hangs in Stopping state and the EXE process has to be killed manually. 我已安排每晚重新启动该服务,但是有时重新启动失败,并且该服务保持/挂起处于“停止”状态,并且必须手动终止EXE进程。 It looks likely that it hangs on line _ESSServiceHost.Close(); 它似乎挂在_ESSServiceHost.Close();行上_ESSServiceHost.Close(); , because nothing after that line is logged it the log file. ,因为该行之后没有任何内容记录到日志文件中。 It is possible but not very likely that the service gets the stop request when it is busy. 服务很可能在忙时获得停止请求。 Moreover the underlying process cannot be killed because it is dependent on services.exe, so only server restart works. 而且,由于依赖于services.exe,因此无法杀死基础进程,因此仅服务器重启有效。

What could be wrong with this approach? 这种方法可能有什么问题?

  protected override void OnStop()
    {
        try
        {
            if (_ESSServiceHost != null)
            {
                _ESSServiceHost.Close();
                _ESSServiceHost = null;
                //Never reaches the following line
                Tools.LogInfo("Services stopped.");
            }
        }
        catch (Exception ex)
        {
            Tools.LogError(ex.Message);
        }

This is how I stop the service: 这是我停止服务的方式:

    private bool StopService(ServiceController scESiftServer)
    {
        int i = 0;
        if (scESiftServer.Status == ServiceControllerStatus.Running)
        {
            try
            {
                scESiftServer.Stop();
            }
            catch (Exception ex)
            {
                Tools.LogEvent("Exception ...");
                return false;
            }
            while (scESiftServer.Status != ServiceControllerStatus.Stopped && i < 120)
            {
                Thread.Sleep(1000);
                scESiftServer.Refresh();
                i++;
            }
        }
        if (scESiftServer.Status != ServiceControllerStatus.Stopped)
        {
            //This line gets executed
            Tools.LogEvent("Failed within 120 sec...");
            return false;
        }
        else
        {
            Tools.LogEvent("OK ...");
        }
        return true;
    }

Could something like this help? 这样的事情可以帮助吗?

var task = Task.Run(() => _ESSServiceHost.Close(TimeSpan.FromSeconds(299)));
if (!task.Wait(TimeSpan.FromSeconds(300)))
{
    _ESSServiceHost.Abort();
}

But _ESSServiceHost.Abort() should be called internally by the Close method if needed. 但是,如果需要,应通过Close方法在内部调用_ESSServiceHost.Abort()。 Target framework is 4.5, installed is .NET 4.7.2. 目标框架是4.5,安装的是.NET 4.7.2。

Found out that probably the service hangs after series of malformed requests. 发现可能是服务在一系列格式错误的请求后挂起。 Expected record type 'Version', found '71'. etc. 等等

I have found in the svclog file that my service hangs after series of malformed request that happen on Saturday and Sunday at approx. svclog文件中,我发现服务在一系列格式错误的请求挂起后发生,这些请求在周六和周日大约发生于。 5:15 AM. 上午5:15。 The error messages were Expected record type 'Version', found '71'. 错误消息为“ Expected record type 'Version', found '71'. , Error while reading message framing format at position 0 of stream (state: ReadingVersionRecord) . Error while reading message framing format at position 0 of stream (state: ReadingVersionRecord) But I could not find the cause of theese malformed request series, so I tried to fix the service to withstand the "attack". 但是我找不到导致这些格式错误的请求系列的原因,因此我尝试修复该服务以承受“攻击”。

I have modified the OnStop method as follows: 我修改了OnStop方法,如下所示:

protected override void OnStop()
{
    try
    {
        if (_ESSServiceHost != null)
        {
            Tools.LogInfo("Stopping ESService.");
            var abortTask = Task.Run(() => _ESSServiceHost.Abort());
            var closeTask = Task.Run(() => _ESSServiceHost.Close(TimeSpan.FromSeconds(300)));
            try
            {
                if (_ESSServiceHost.State == CommunicationState.Faulted)
                {
                    Tools.LogInfo("ESSServiceHost.State == CommunicationState.Faulted");
                    if (!abortTask.Wait(TimeSpan.FromSeconds(60)))
                        Tools.LogInfo("Failed to Abort.");
                }
                else
                {
                    if (!closeTask.Wait(TimeSpan.FromSeconds(301)))
                    {
                        Tools.LogInfo("Failed to Close - trying Abort.");
                        if (!abortTask.Wait(TimeSpan.FromSeconds(60)))
                            Tools.LogInfo("Failed to Abort.");

                    }                            
                }
            }
            catch (Exception ex)
            {
                Tools.LogException(ex, "ESSServiceHost.Close");
                try
                {
                    Tools.LogInfo("Abort.");
                    if (!abortTask.Wait(TimeSpan.FromSeconds(60)))
                        Tools.LogInfo("Failed to Abort.");
                }
                catch (Exception ex2)
                {
                    Tools.LogException(ex2, "ESSServiceHost.Abort");

                }
            }
            _ESSServiceHost = null;
            Tools.LogInfo("ESService stopped.");
        }
    }
    catch (Exception ex)
    {
        Tools.LogException(ex,"OnStop");
    }
}

Today on Monday I have checked the svclog and the "attacks" with malformed request remained there but my service lived happily through it. 今天星期一,我检查了svclog,并在请求中保留了格式错误的“攻击”,但我的服务过得很愉快。 So it seemed to be fixed. 因此,它似乎是固定的。 Moreover only: 而且只有:

Stopping ESService. 停止ESService。

ESService stopped. ESService已停止。

events were logged in my log file. 事件已记录在我的日志文件中。 No aborts etc. So I guess that putting the Close call on a separate thread fixed the problem but absolutely do not know why. 没有中止等。所以我想将Close调用放在单独的线程上可以解决问题,但绝对不知道为什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM