内循环时如何允许消息

时间:2013-12-20 14:18:37

标签: c# events message-queue

我编写了模拟寻路算法的应用程序。我可以运行算法或步骤(如调试)。但是当我运行算法时,我无法在算法完成之前绘制任何更改。

private void menu_run_Click(object sender, EventArgs e)
{
    algorithm.Reset();
    while (algorithm.status == Algorithm.Status.Searching )
    {
        algorithm.MakeStep();
        if (this.speed != 0) System.Threading.Thread.Sleep(this.speed);

        drawing_area.Invalidate();
    }
}

我想这是因为我在一个周期内完成所有操作,系统无法处理我触发的新消息(事件)。

那么我应该如何更改代码以便能够在每次迭代后重绘更改?

  1. 我应该以某种方式调用Message Dispatcher让他在每次迭代后处理新消息吗?
  2. 我应该创建自己的消息并使用消息在循环内完成所有工作吗?
  3. 或者我有更优雅的方式吗?

1 个答案:

答案 0 :(得分:1)

有很多不同的方法可以做到这一点。

可以说,最简单的方法是在表单上使用System.Windows.Forms.Timer对象,而不是在无限循环中调用Sleep()

  1. 从工具箱中将计时器添加到表单中。
  2. 将其Interval属性设置为this.speed
  3. 将其Enabled属性设置为true
  4. 订阅计时器的Tick活动。
  5. 处理程序看起来像这样:

    private void OnTimerTick(object sender, EventArgs e)
    {
        if (algorithm.Status == Algorithm.Status.Searching)
        {
            algorithm.MakeStep();
            drawing_area.Invalidate();
        }
    }
    

    您可能需要稍微重新排列控制逻辑(算法启动和停止的位置)。如果有帮助,您可以使用计时器的Enabled属性。

    另一种解决方案是创建一个带有后台线程的对象,该算法在算法运行时会引发周期性事件,并且表单会订阅这些事件并相应地重绘(不要忘记在事件上使用Invoke因为它们将来自非GUI线程。)

    还有BackgroundWorker您可以将其作为第三种选择。但我认为计时器对你来说最简单。