.ShowDialog()显示两次

时间:2014-12-27 14:02:46

标签: c# winforms timer duplicates showdialog

我有一个恼人的问题...... 我只想展示一个对话框,但它总是显示两次......这里是代码:

    private void tmr_sysdt_Tick(object sender, EventArgs e)
    {
        lbl_time.Text = System.DateTime.Now.ToLongTimeString();
        lbl_date.Text = System.DateTime.Now.ToLongDateString();
        if (GetLastInputTime() > Program.timeout)
        {
            frm_lockscreen login= new frm_lockscreen();
            tmr_sysdt.Enabled = false;
            if (login.ShowDialog(this) == DialogResult.OK) tmr_sysdt.Enabled = true;
        }
    }

tmr_sysdt.Interval is 1000

问题很简单 - 但对我来说无法解决 - 对话框一式两份显示(第二个是第一个出现在同一时间)。

我不知道,所以任何想法都会受到赞赏:)

谢谢,如果您需要更多详细信息,请发表评论!

Ps。:对不好的英国人抱歉


编辑:GetLastInputTime()

    [DllImport("user32.dll")]
    static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
    static uint GetLastInputTime()
    {
        uint idleTime = 0;
        LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
        lastInputInfo.cbSize = (uint)Marshal.SizeOf(lastInputInfo);
        lastInputInfo.dwTime = 0;

        uint envTicks = (uint)Environment.TickCount;

        if (GetLastInputInfo(ref lastInputInfo))
        {
            uint lastInputTick = lastInputInfo.dwTime;

            idleTime = envTicks - lastInputTick;
        }

        return ((idleTime > 0) ? (idleTime / 1000) : 0);
    }

    [StructLayout(LayoutKind.Sequential)]
    struct LASTINPUTINFO
    {
        public static readonly int SizeOf = Marshal.SizeOf(typeof(LASTINPUTINFO));

        [MarshalAs(UnmanagedType.U4)]
        public UInt32 cbSize;
        [MarshalAs(UnmanagedType.U4)]
        public UInt32 dwTime;
    }

3 个答案:

答案 0 :(得分:1)

你能试试这段代码吗?只是为了确保处理程序中的逻辑不会同时被调用两次:

    static bool busy = false;
    private void tmr_sysdt_Tick(object sender, EventArgs e)
    {
        if (busy)
        {
            return;
        }
        busy = true;
        try
        {
            lbl_time.Text = System.DateTime.Now.ToLongTimeString();
            lbl_date.Text = System.DateTime.Now.ToLongDateString();
            if (GetLastInputTime() > Program.timeout)
            {
                frm_lockscreen login = new frm_lockscreen();
                tmr_sysdt.Enabled = false;
                if (login.ShowDialog(this) == DialogResult.OK) tmr_sysdt.Enabled = true;
            }
        }
        finally
        {
            busy = false;
        }
    }

您遇到的问题是检查用户上次活动并显示登录框的代码是多次创建的形式。
事实上,这些“主要形式”中的每一个都在检查用户活动并显示登录框。

通过将busy bool设置为static,'main form'的每个实例都将此bool读为相同的值。因此,check + show login仅执行一次。

我建议将此代码移动到您只创建一次的表单,并在应用程序的整个生命周期内保持打开状态。 (如果你有这样的表格)

答案 1 :(得分:1)

您想重复使用frm_lockscreen并阻止重新进入Tick事件

private frm_lockscreen _lockScreen;

private frm_lockscreen LockScreen
{
    get { return _lockScreen ?? (_lockScreen = new frm_lockscreen()); }
}

private void tmr_sysdt_Tick(object sender, EventArgs e)
{
    // prevent reentry
    if (!Monitor.TryEnter(tmr_sysdt)) return;

    try {
        lbl_time.Text = System.DateTime.Now.ToLongTimeString();
        lbl_date.Text = System.DateTime.Now.ToLongDateString();
        if (GetLastInputTime() > Program.timeout)
        {
            tmr_sysdt.Enabled = false;
            if (LockScreen.ShowDialog(this) == DialogResult.OK) tmr_sysdt.Enabled = true;
        }
    }
    finally {
        Monitor.Exit(tmr_sysdt);
    }
}

答案 2 :(得分:0)

原因是你的外部if条件返回true两次:

if (GetLastInputTime() > Program.timeout)

要查找罪魁祸首,您必须检查GetLastInputTime()和Program.Timeout返回的值