.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 ответа

Решение

Не могли бы вы попробовать этот код? Просто чтобы убедиться, что логика в вашем обработчике не вызывается дважды одновременно:

    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;
        }
    }

Проблема, с которой вы столкнулись, заключалась в том, что код для проверки последней активности пользователя и отображения поля входа в систему был в форме, которая создается несколько раз.
Фактически, каждая из этих "основных форм" проверяла активность пользователя и показывала окно входа в систему.

Помещая занятый bool как статический, каждый экземпляр "главной формы" считывает этот bool как одно и то же значение. Следовательно, логин check+show выполняется только один раз.

Я бы предложил переместить этот код в форму, которую вы создаете только один раз, и держать открытой в течение всего срока службы приложения. (Если у вас есть такая форма)

Вы хотите повторно использовать свой экран frm_lock и предотвратить повторный вход в событие 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);
    }
}

Причина в том, что ваше внешнее условие if возвращает true дважды:

if (GetLastInputTime() > Program.timeout)

Чтобы найти виновника, вы должны проверить значения, возвращаемые GetLastInputTime() и Program.Timeout

Другие вопросы по тегам