Вызывает ли Application.DoEvents в основном потоке то же, что и в ThreadPool?

Мы пытаемся автоматизировать тестирование старого устаревшего кода. Есть форма, которая открывается, запускает таймер и читает данные из порта. Юнит-тест открывает форму, но таймер не ставится до тех пор, пока Application.DoEvents не запустит процесс обработки очереди сообщений Windows. Он отличается тем, что выполняется из unittest, а Application.Run не является частью кода.

Но мы не можем заблокировать поток unittest с помощью Application.DoEvents, потому что нам нужно подождать и проверить данные с помощью assert.

ThreadPool.QueueUserWorkItem(x =>
{
    While(!form.workFinished)
    { 
         Application.DoEvents();
         Thread.Sleep(50);
    }
    synchronization.Set();
});
synchronization.WaitOne();

Assert.AreEqual(10000, form.recorded.Count);

Но этот фрагмент не делает то, что я ожидал. Это отличается от выполнения формы из приложения WinForm? Могу ли я вызвать Application.DoEvents из пула потоков?

Я действительно не хочу на самом деле не изменять старый код. Мне просто нужно, чтобы unittest работал над текущим решением.

1 ответ

Решение

Лучший способ сделать это - запустить форму в обычном режиме с помощью Application.Run. Когда тест завершен, закройте форму или вызовите Application.Exit в этом потоке.

DoEvents качает события в текущем потоке. Там может быть несколько потоков пользовательского интерфейса. DoEvents влияет только на текущий.

Ваш код модульного теста может выглядеть так:

Form form = null;
var task = Task.Factory.StartNew(() => {
 form = new Form(); //Run ctor on UI thread.
 Application.Run(form);
}, LongRunning);

//Work with the form here.

form.Invoke(() => Application.Exit());
task.Wait();

Это всего лишь эскиз. Синхронизация отсутствует, и я уверен, что есть другие вещи, которые нужно решить для вас.

LongRunning гарантирует, что GUI работает на новом потоке каждый раз. Это предотвращает утечки состояния из теста в тест.

По сути, это стандартный поток пользовательского интерфейса плюс модель рабочего потока. Здесь поток модульного тестирования является рабочим, и необходимо создать поток пользовательского интерфейса. Обычно поток пользовательского интерфейса будет Main нить и рабочий будет создан.

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