【问题标题】:Setting DateTimePicker closes application only when triggered from timed action设置 DateTimePicker 仅在从定时操作触发时关闭应用程序
【发布时间】:2011-12-17 13:33:47
【问题描述】:

我在 C# 中有一个函数,它一开始将 GUI 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# execute action after X seconds)

【问题讨论】:

  • 该代码存在严重问题。隐藏线程是一个非常糟糕的主意。一个垃圾收集器让它消失得无影无踪,烤蛋糕。扔掉它,只需使用 Winforms 计时器。不要隐藏它。

标签: c# datetimepicker timed-events


【解决方案1】:

控件不是线程安全的,这意味着您不能从另一个线程调用控件的方法。您可以等到控件的线程准备好使用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();
}

【讨论】:

  • 我测试了您的建议并且它有效,但是稍后在函数和计时器调用的其他函数中我有额外的 GUI 调用。因此,我不会更改每个相关的 GUI 调用,而是尝试通过实现下面的第二个解决方案来限制对计时功能的更改。不过谢谢!
  • 假设所有控件都在同一个线程中创建,您可以在单个Control.Invoke 调用中完成所有操作,您不必为每个方法调用创建单独的Actions。不过我同意,使用另一个 Timer 可能更容易,并且避免了你并不真正需要的线程。祝你好运。
【解决方案2】:

您正试图从另一个线程修改 GUI 元素,由 At.Do() 隐式创建。见this thread。

在At.Do() 中使用System.Windows.Forms.Timer 而不是System.Threading.Timer 可能会解决问题。 (只需将new Timer(...) 更改为new System.Windows.Forms.Timer(...)。)

【讨论】:

  • 实际上只是将System.Threading.Timer 更改为System.Windows.Forms.Timer 不起作用,因为System.Windows.Forms.Timer 没有4 参数重载。但是,一般来说,这可能是更方便的修复,因为只有计时功能会受到影响。你知道如何让System.Windows.Forms.Timer 调用复制new System.Threading.Timer(TimerCallback timer, Action action, int delayMilliseconds, int interval) 的功能吗?
  • This page 有一个例子。您创建一个timer,设置它的Tick 事件和Interval 属性,然后调用它的Start 方法。您没有用于此的单行构造函数,但它几乎相同。
  • 我之前浏览过该页面,但是如何使定时事件在设定的时间每天(或一次性)发生一次?我可以计算 runtime 和 event-schedule-time 之间的时间差并将其用作 Interval,但是如何防止事件执行在该设置的 Interval 处重复发生?
  • 从事件处理程序内部调用myTimer.Stop();。 (参见同一页中的示例)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-17
  • 2016-05-07
相关资源
最近更新 更多