【问题标题】:Ticker generated forms not displaying correctly股票代码生成的表格未正确显示
【发布时间】:2012-04-30 12:01:25
【问题描述】:

希望这不会太难理解。

我目前正在开发一个在后台安静运行的小型时间记录应用程序。每次代码运行结束时,应用程序都会提示用户说出自上次提示以来他/她在做什么。我最终会让应用程序将数据写入电子表格。

到目前为止,我有一个选项使用户能够选择他/她是否要使用默认提示设置(每次错过提示时,它都会保持可见,直到创建下一个提示,这意味着如果用户离开他/她的计算机一段时间后,屏幕上可能会有相当多的提示等待填写)或想要合并所有提示(每次错过提示并弹出一个新提示时,旧提示关闭,新提示覆盖旧提示和新提示的时间)。

用户还可以选择一个复选框来关闭提示。当他/她再次打开提示时,会弹出一个提示,要求用户填写他/她在关闭提示时所做的事情(在用户运行全屏应用程序等时很有用)。

我的问题是,当我尝试生成提示时,它们无法正确显示。我根本无法操纵它们,也没有任何控件显示。它们基本上看起来像空表格。

这是我使用代码生成提示的代码:

public void ticker(object source, System.Timers.ElapsedEventArgs e)
    {
        if (groupMissed)
        {
            incrementsMissed += 1;
            if (incrementsMissed > 1)
            {
                IncrementForm form = (IncrementForm)Application.OpenForms["IncrementForm"];
                if (form.InvokeRequired)
                {
                    form.Invoke(new MethodInvoker(delegate { form.Close(); }));
                }
            }
        }
        else
        {
            incrementsMissed = 1;
        }

        IncrementForm theIncrementForm = new IncrementForm(this, e.SignalTime);
        theIncrementForm.Show();
        latestIncrement = e.SignalTime;
    }

这是我使用“关闭提示”复选框生成提示的代码:

private void chkbxAlerts_Click(object sender, EventArgs e)
    {
        if (!chkbxAlerts.Checked)
        {
            // Ensures that the time missed is covered and restarts the timer
            DateTime now;
            now = DateTime.Now;
            if ((now - latestIncrement).TotalMinutes >= 1) // Only records time if it is equal to or greater than one minute
            {
                // TO-DO: FIX
                if (groupMissed)
                {
                    incrementsMissed += 1;
                    if (incrementsMissed > 1)
                    {
                        IncrementForm form = (IncrementForm)Application.OpenForms["IncrementForm"];
                        if (form.InvokeRequired)
                        {
                            form.Invoke(new MethodInvoker(delegate { form.Close(); }));
                        }
                    }
                }
                else
                {
                    incrementsMissed = 1;
                }
                IncrementForm theIncrementForm = new IncrementForm(this, now, latestIncrement);
                theIncrementForm.Show();
                latestIncrement = now;
            }
            timer.Enabled = true;
        }
        else
        {
            // Stops the timer
            timer.Enabled = false;
        }
    }

如果您需要任何进一步的说明,请告诉我。非常感谢您的帮助,这一直困扰着我。

【问题讨论】:

  • 一个非常完善的问题 - 尽管仍然缺少一些东西。你的股票是计时器驱动的吗?计时器正在从另一个线程调用 - 您无法从那里更新 GUI 表单(尽管您可以在不同的线程中显示/生成表单 - 不确定在您的情况下最终会“给予”什么)...是的,那肯定是另一个线程
  • 是的,ticker 由计时器上的 Elapsed 事件调用。我怎样才能解决你提到的这个 GUI 问题?
  • 您能制作一个小的“可运行”示例吗?我猜还有更多内容
  • @NSGaga 我只是做了一些快速的研究并意识到问题确实是因为我试图在计时器线程中执行 UI 功能,就像你说的那样。我只需要弄清楚如何通过 UI 线程线程化所述功能。这是令人困惑的事情。
  • 你有一个一直在运行的主窗口吗?

标签: c# forms prompt ticker


【解决方案1】:

我认为,据我所知,不是 100%,而是您的计时器在一个单独的线程中生成了您的窗口(来自计时器代码调用)。

虽然理论上可行(看看这个How to open a form in a thread and force it to stay open
...您最好留在主线程中。

试试这样的……

yourMainWindow.Invoke(new MethodInvoker(() =>
    {
        IncrementForm theIncrementForm = new IncrementForm(this, e.SignalTime);
        theIncrementForm.Show();
        latestIncrement = e.SignalTime;
    }));

...那是来自你的计时器 - 这样(如我所见)你应该把它全部放在“主线程”上,让你的事情变得更容易。

希望对你有帮助

【讨论】:

  • 非常感谢您的帮助!尽管我最终没有使用您的方法,但您确实帮助我更多地了解了线程。再次感谢!
【解决方案2】:

System.Timers.Timer 有一个SynchronizingObject 属性。如果将其设置为主窗体(或包含计时器的窗体),则将在 GUI 线程上引发计时器滴答事件。

请注意System.Timers.Timer 有吞下Elapsed 事件中发生的异常的讨厌习惯。如果您的刻度处理程序抛出异常,您将永远不会看到它。这是一个讨厌的虫子隐藏器。因此,我建议使用System.Windows.Forms.TimerSystem.Threading.Timer。如果您使用 Windows 窗体计时器,则在 GUI 线程上引发 elapsed 事件。如果您使用 System.Threading.Timer,则必须使用 Invoke,正如 NSGaga 在他的回答中显示的那样。

请参阅Swallowing exceptions is hiding bugs,了解我为什么不鼓励使用System.Timers.Timer

【讨论】:

  • 您的解决方案效果很好,谢谢!就一件事。 System.Windows.Forms.Timer 似乎没有等效于 System.Timers.ElapsedEventArgs.SignalTime 所以我只是使用 DateTime.Now 代替。认为您可能想知道您是否还没有。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-23
  • 1970-01-01
  • 1970-01-01
  • 2019-12-24
  • 1970-01-01
  • 2012-02-23
相关资源
最近更新 更多