2013-12-20 2 views
0

Я пишу приложение, которое имитирует алгоритмы поиска пути. Я могу запустить алгоритм или выполнить его (например, отладка). Но когда я запускаю алгоритм, я не могу сделать никаких изменений до тех пор, пока алгоритм не будет выполнен.Как разрешить сообщения во внутреннем цикле

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. Или нет более элегантного способа я?
+0

В качестве быстрого ответа 'Application.DoEvents' запускает обработку очереди сообщений, поэтому может потребоваться то, что вы хотите. Вызовите его после 'Invalidate', и он должен обработать перерисовку области рисования. Тем не менее, компонент Timer, вероятно, будет более полезен. – Luaan

ответ

1

Существует много разных способов сделать это.

Возможно, самым простым для вашей ситуации было бы использовать объект System.Windows.Forms.Timer на вашей форме, а не называть Sleep() в неопределенном цикле.

  1. Добавить таймер в вашу форму на панели инструментов.
  2. Установить Interval собственности this.speed.
  3. Свойство Enabledtrue.
  4. Подпишитесь на событие Tick таймера.

обработчик будет выглядеть примерно так:

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

Вы, вероятно, нужно немного изменить логику управления (где запускается алгоритм и остановлен). Вы можете использовать свойство Enabled таймера для этого, если это поможет.

Другим решением будет создание объекта с фоновым потоком, который вызывает периодические события по мере запуска алгоритма, и форма будет подписана на эти события и соответствующим образом перерисована (не забудьте использовать Invoke для событий, будет поступать из потока, отличного от GUI).

Существует также BackgroundWorker, который вы могли бы изучить в качестве третьей альтернативы. Но я думаю, что таймер будет проще для вас.

Смежные вопросы