Настройка DateTimePicker закрывает приложение, только если оно вызвано действием по времени

У меня есть функция в C#, которая вначале устанавливает значение объекта DateTimePicker с графическим интерфейсом на сегодняшнюю дату (время = полночь), а затем выполняет другие действия. При выполнении через кнопку GUI функция (DBIO_Morning) работает нормально. Но выполняется через синхронизированное действие:

private void SetupTimedActions()
{
   ...

   DateTime ref_morning = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 8, 16, 0);
   if (DateTime.Now < ref_morning)
      At.Do(() => DBIO_Morning(), ref_morning);
   ...
}

это терпит неудачу во второй строке:

private void DBIO_Morning()
{
   DateTime date_current = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 0, 0, 0);
   DTPicker_start.Value = date_current;
   ...
}

(Объект At.Do от третьего ответа здесь: C# выполнить действие через X секунд)

2 ответа

Решение

Элементы управления не являются потокобезопасными, то есть вы не должны вызывать методы элемента управления из другого потока. Вы можете подождать, пока поток элемента управления не будет готов обработать ваше действие, используя Control.Invoke:

private void DBIO_Morning()
{
    DateTime date_current = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 0, 0, 0);
    Action setValue = () => DTPicker_start.Value = date_current;
    if (DTPicker_start.InvokeRequired)
        DTPicker_start.Invoke(setValue);
    else
        setValue();
}

Вы пытаетесь изменить элементы графического интерфейса из другого потока, созданного неявно At.Do(), Смотрите эту ветку.

С помощью System.Windows.Forms.Timer в At.Do() вместо System.Threading.Timer вероятно, решит проблему. (Просто поменяй new Timer(...) в new System.Windows.Forms.Timer(...).)

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