.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