Невозможно воспроизвести ошибку «многопотоковая операция не действительна» в модульных тестах - я не понимаю - PullRequest
2 голосов
/ 06 ноября 2011

Это мой первый вопрос стека, поэтому заранее прошу прощения, если мой формат или этикет немного не в порядке.

Недавно я настраивал шаблоны для обработки «недопустимая операция между потоками» выдает при взаимодействии с элементами управления WinForms из отдельного потока.

Я подумал, что было бы неплохо настроить модульный тест, чтобы изолировать это, и утверждать, что мои расширения SynchronisationContext устранили проблему, поэтому я создал простую форму тестирования с одной кнопкой на ней и некоторым кодом, который называется PerformClick () из другого потока, чтобы повторить проблему:

    [STAThread]
    static void Main()
    {           
        using (TestForm form = new TestForm())
        {
            Thread t1 = new Thread(() => Application.Run(form));
            Thread t2 = new Thread(() => form.buttonStart.PerformClick());
            form.Activated += (sender, args) => t2.Start();
            t1.Start();
            Thread.Sleep(1000); //Prevents form from being disposed before 'click' can occur from other thread.
        }                       
    }

Тестовая форма - это буквально пустая форма с одной кнопкой на ней. Когда я запустил этот код, я получил ожидаемое исключение операции между потоками.

Но когда я помещаю код в тест NUnit, исключение не возникает. Вот мой юнит тест:

    [Test]
    public void PostToControl_AcrossThreads()
    {           
        //Notes: This code normally generates a cross-thread exception.
        //For some reason, when you run it in the scope of the unit test, the exception is not generated.
        using (TestForm form = new TestForm())
        {
            Thread t1 = new Thread(() => Application.Run(form));
            Thread t2 = new Thread(() => form.buttonStart.PerformClick());
            form.Activated += (sender, args) => t2.Start();
            t1.Start();
            Thread.Sleep(1000); //Prevents form from being disposed before 'click' can occur from other thread.
        }
    }

Я понял, что понятия не имею, почему это произойдет, поэтому я бросаю это экспертам :-)

Может ли кто-нибудь просветить меня? Что происходит в модульном тесте по-другому, по сравнению с собственным запуском формы?

Ответы [ 3 ]

3 голосов
/ 06 ноября 2011

Используйте что-то другое, чем PerformClick(). Например form.buttonStart.Text = "This is my form"; или изменение позиции и т. Д. *

Причина в том, что метод PerformClick() вызывает только событие .NET Click. Но проблема многопоточной работы заключается в цикле сообщений Windows. Поэтому, если вы хотите «сделать проблему», вы должны выполнить какое-то действие, использующее цикл сообщений Windows.

2 голосов
/ 06 ноября 2011

Это поведение контролируется свойством: Control.CheckForIllegalCrossThreadCalls

По умолчанию это верно только в том случае, если подключен отладчик, то есть поведение, которое вы видите.

0 голосов
/ 06 ноября 2011

Может ли кто-нибудь просветить меня? Что происходит по-другому в блоке тест по сравнению с запуском формы?

нет ничего другого.

если вам нужно проверить исключение в Nunit, лучше используйте Exception Asserts . в противном случае nunit не покажет исключения для вас.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...