【问题标题】:Timers in C# with Global variables?C# 中带有全局变量的定时器?
【发布时间】:2016-07-21 02:51:16
【问题描述】:

我对下面的代码有一些问题。

当应用程序运行时,只要LookingAwayResult.Text = "Yes",计时器就会启动并计数到 10。当 LookingAwayResult.Text = "No""Maybe" 时,计时器应该停止并再次重置回 0,但这不会。

当计时器达到 10 时,会出现一个消息框,这是我想要的,但这会继续显示并在我的屏幕上显示垃圾邮件。计时器用于在消息框出现后重置为 0,并且应用程序冻结,直到在消息框上选择“Ok”。

似乎我的代码正在循环所有不是我想要的计时器。

private void OnFaceFrameArrived(object sender, FaceFrameArrivedEventArgs e)
{
    // Retrieve the face reference
    FaceFrameReference faceRef = e.FrameReference;

    if (faceRef == null) return;

    // Acquire the face frame
    using (FaceFrame faceFrame = faceRef.AcquireFrame())
    {
        if (faceFrame == null) return;

        // Retrieve the face frame result
        FaceFrameResult frameResult = faceFrame.FaceFrameResult;

        // Display the values
        HappyResult.Text = frameResult.FaceProperties[FaceProperty.Happy].ToString();
        EngagedResult.Text = frameResult.FaceProperties[FaceProperty.Engaged].ToString();
        GlassesResult.Text = frameResult.FaceProperties[FaceProperty.WearingGlasses].ToString();
        LeftEyeResult.Text = frameResult.FaceProperties[FaceProperty.LeftEyeClosed].ToString();
        RightEyeResult.Text = frameResult.FaceProperties[FaceProperty.RightEyeClosed].ToString();
        MouthOpenResult.Text = frameResult.FaceProperties[FaceProperty.MouthOpen].ToString();
        MouthMovedResult.Text = frameResult.FaceProperties[FaceProperty.MouthMoved].ToString();


        //initilize look away timer for 10 seconds
        Timer lookAwayTimer = new Timer(interval: 10000);

        //inialize the poll tiomer for 50 ms
        Timer pollTimer = new Timer(interval: 50);


        LookingAwayResult.Text = frameResult.FaceProperties[FaceProperty.LookingAway].ToString();

        //if 10 seconds expires then show message box
        lookAwayTimer.Elapsed += (s, f) =>
        {
            MessageBox.Show("Looking is set to yes", "Looking Error", MessageBoxButton.OK);
        };

        //enable poll timer
        pollTimer.Enabled = true;

        //check if person is looking. If they are not then enable the lookAwayTimer.  If they start looking
        //then disable the timer
        pollTimer.Elapsed += (s, f) =>
        {
            Check = frameResult.FaceProperties[FaceProperty.LookingAway].ToString();

            if (Check == "Yes")
            {
                lookAwayTimer.Enabled = true;
            }
            else
            {
                lookAwayTimer.Enabled = false;
            }
        };
    }
}

我所追求的是在该人不看并停止后运行计时器,并在该人再次看时重置回0。

当计时器达到 10 秒时,会出现消息框并且应用程序会冻结。用户必须选择“确定”才能使此框消失并且应用程序重置为默认值。

根据研究,我相信在这里使用全局变量或模态框可能会派上用场?

我相信使用模态框会冻结我的应用程序,直到用户对其进行操作?但这仍然不能解决我的问题,即计时器没有重置回 0,并且希望应用程序在选择“确定”后完全重置。

我也很喜欢 C# 中的全局变量,除非必要,否则应该避免使用。

如果模态框是其中一部分的答案,我是否只需将MessageBox.Show 更改为ShowDialog

【问题讨论】:

    标签: c# timer global-variables


    【解决方案1】:

    从您的问题可以看出,您没有控制单击消息框按钮的任何操作。您可能仅显示消息框以通知用户。

    为了让您的代码在执行时不会暂停,请在 different thread 上创建消息框,这样执行就不会停止。

    以下代码在单独的线程上创建一个消息框。

     public class ThreadIndependentMB
        {
            private readonly Dispatcher uiDisp;
            private readonly Window ownerWindow;
    
            public ThreadIndependentMB(Dispatcher UIDispatcher, Window owner)
            {
                uiDisp = UIDispatcher;
                ownerWindow = owner;
            }
    
            public MessageBoxResult Show(string msg, string caption="",
                MessageBoxButton buttons=MessageBoxButton.OK,
                MessageBoxImage image=MessageBoxImage.Information)
            {
                MessageBoxResult resmb = new MessageBoxResult();
                if (ownerWindow != null)
                uiDisp.Invoke(new Action(() =>
                {
                    resmb = MessageBox.Show(ownerWindow, msg, caption, buttons, image);
    
                }));
                else
                    uiDisp.Invoke(new Action(() =>
                    {
                        resmb = MessageBox.Show( msg, caption, buttons, image);
    
                    }));
                return resmb;
            }
    
    
        }
    

    在您的计时器中,您可以实例化该类并调用该类的 Show 方法。

    【讨论】:

    • 我怎样才能实现这个代码来完成我对计时器的要求?我需要改变什么?
    • 只要做一个上面类的对象,在elapsed事件中调用类的show方法,而不是MessageBox.Show()
    【解决方案2】:

    计时器上的AutoReset 属性可能会解决您的问题:

    System.Timers.Timer lookAwayTimer = new System.Timers.Timer(10000)
    {
        AutoReset = false
    };
    
    lookAwayTimer.Elapsed += (object sender, System.Timers.ElapsedEventArgs e) =>
        {
            pollTimer.Stop();
            MessageBox.Show("Looking is set to yes", "Looking Error", MessageBoxButtons.OK);
            lookAwayTimer.Start();
            pollTimer.Start();
        };
    

    将此设置为 false 将导致计时器经过一次然后停止重复(因此它不会向您的屏幕发送垃圾邮件),直到您再次启动它 - 默认为 true,因此它将保持自动重置并每 10 秒调用一次此方法。

    【讨论】:

    • 我试过了,消息框一直出现:(
    • @lfctez 也许您也应该停止轮询计时器?由于它仍在运行,并且即使消息已弹出,也会重新启用lookAwayTimer?我已经用你可以做到的方式更新了我的答案。
    • 试过了,还是一样,抱歉:(
    • 没问题——我能推荐的就是把这个简单的例子放到一个新项目中,确保它像你期望的那样工作,然后尝试看看它与你的项目有什么不同——祝你好运!。
    • 感谢您的帮助和时间。我试试看!
    猜你喜欢
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-12
    • 1970-01-01
    相关资源
    最近更新 更多