在侦听串行端口处理程序后,Windows服务在主流程中的Thread.sleep()上运行到睡眠模式,并挂起到空闲模式C#

在侦听串行端口处理程序后,Windows服务在主流程中的Thread.sleep()上运行到睡眠模式,并挂起到空闲模式C#,c#,multithreading,windows-services,C#,Multithreading,Windows Services,我在C#中执行windows服务时遇到问题,不确定,但可能是由于侦听事件处理程序的线程与正常代码流之间的死锁。当侦听事件并返回到执行Thread.Sleep的正常流时,服务将挂起。windows服务在第一次正常进入睡眠模式,下一次持续时间自动加倍,此后它将永远不会唤醒,服务将进入“死锁”模式 下面的snippet controller.DeviceState中有一个全局变量,事件侦听器和主流都使用该变量。所有异常都已处理。请让我知道为什么代码会进入“永不醒来的睡眠模式” 以下是一般代码流程: 主

我在C#中执行windows服务时遇到问题,不确定,但可能是由于侦听事件处理程序的线程与正常代码流之间的死锁。当侦听事件并返回到执行Thread.Sleep的正常流时,服务将挂起。windows服务在第一次正常进入睡眠模式,下一次持续时间自动加倍,此后它将永远不会唤醒,服务将进入“死锁”模式

下面的snippet controller.DeviceState中有一个全局变量,事件侦听器和主流都使用该变量。所有异常都已处理。请让我知道为什么代码会进入“永不醒来的睡眠模式”

以下是一般代码流程:

主要服务

public partial class MainService : ServiceBase
{

    protected override void OnStart(string[] args)
    {
        try
        {

            ThreadStart start = new ThreadStart(MainProcess); 

            Thread mainProcessThread = new Thread(start);

            // set flag to indicate worker thread is active
            serviceStarted = true;

            // start threads
            mainProcessThread.Start();
        }
        catch(Exception ex)
        {
            //catch exception
        }
    }

    string testVariable = "YES";


    //Event handler
    private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        System.IO.Ports.SerialPort sp = (System.IO.Ports.SerialPort)sender;
        string s = sp.ReadExisting();

        if (s == "Wifi")
        {
            testVariable = "NO";
        }
    }

    private void MainProcess()
    {

        try
        {
            int i = 0;

            System.IO.Ports.SerialPort sp = new System.IO.Ports.SerialPort("COM4");

            sp.Open();
            sp.DataReceived += serialPort1_DataReceived;

            sp.BaudRate = 9600;
            sp.DataBits = 8;
            sp.Parity = System.IO.Ports.Parity.None;
            sp.StopBits = System.IO.Ports.StopBits.One;
            sp.Handshake = System.IO.Ports.Handshake.None;
            sp.DtrEnable = true;

            while (testVariable == "YES")
            {

                i++;
                //Sleep until the testVariable is set to NO
                Thread.Sleep(5000);
            }


        }
        catch(Exception ex)
        {
            //catch exception here
        }
    }

    protected override void OnStop()
    {

    }
}

我想现在我真的找到了导致僵局的原因。为了复制,我将睡眠时间增加到20秒,然后运行。我发现,当在这段时间(睡眠时间)内从事件处理程序中检索到消息时,整个应用程序都会进入挂起模式,我不理解实际原因,但在线程中。睡眠还会阻止任何事件处理程序进行侦听,如果它这样做,整个系统将进入“死”模式

为了修复它,我在main类中初始化

private static AutoResetEvent event_1 = new AutoResetEvent(true);
并添加了event_1.Set();线程之前。睡眠如下:

while (testVariable == "YES")
{
     Common.WriteLogIntoFile("i", i.ToString(), "FaxWorker()");
     i++;
     event_1.Set();
     Thread.Sleep(20000);
 }

但我不知道它是如何修复的,如果有人知道,请告诉我。

它在控制台应用程序或单元测试中运行正常吗?通常,当我编写服务时,我至少有三个项目。业务逻辑、服务运行程序和控制台运行程序。这样,在部署服务之前,我可以在console runner中完成所有调试。我还有一个界面,用于使用控制台记录器和windows事件查看器记录器进行日志记录。在调试器无法连接的服务中运行时,日志记录可以帮助进行故障排除。乍一看,一切都很好。这应该没有什么区别,但是对于System.Timers.Timer而不是一个新线程来说是一样的吗?另外,我知道这与我更喜欢服务的计时器无关,因为thread.Sleep会阻止一个线程,而计时器从操作系统获得回调,并且是为这种类型的工作而设计的,因此,浪费的CPU周期更少,事件驱动触发器更多:)从概念上讲,我认为它们应该都能正常工作,所以这条评论与问题无关。您需要发布至少足够的代码来说明为什么希望它做任何事情。目前,我们甚至不知道OnDataReceived方法与哪个继承类有关。@Joe_DM:我曾使用System.Timers.Timer线程,但后来我知道,这样做会创建自己的线程,并与thread.Sleep冲突,从而再次导致挂起模式。@Harry Johnston:datareceived使用SerialDataReceiveDevenHandler,即从串行端口接收数据的类。
OnDataReceived
是否实际接收过“00”?您是否考虑过它单独接收每个字符的可能性,即,两个连续的“0”呼叫,而不是一个“00”呼叫?您是否检查了此主题@瓦塞克:与我的问题无关,数据正在接收中,不是问题。这里的问题是,一旦启动thread.sleep,windows服务将进入从不唤醒模式,同时串行端口将消息发送到OndataReceived事件侦听器,因此发送的消息将永远不会收到。请尝试将代码复制到console应用程序中,看看这是否有帮助。它可能与服务有关。如果它没有帮助,你的应用程序仍然是坏的,在这里张贴完整的最小可复制代码。它应该很容易复制,因为你的终止字符串从未收到过。@vasek:我第一篇文章中的代码是可行的。的确,在控制台应用程序中,我们不需要任何线程作为windows服务启动进程,因此这些事情不会在那里发生,也不会在windows窗体应用程序中发生。