这是我的第一个Stack问题,如果我的格式或礼仪稍微偏离,请提前道歉。
我最近在从单独的线程与WinForms控件交互时设置了处理'cross-thread operation not valid' issues的模式。
我认为设置一个单元测试以隔离它并断言我的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.
}
}
我意识到我不清楚为什么会这样,所以我把它扔给专家:-)
任何人都可以开导我吗?与单独运行表单相比,单元测试中发生的情况如此不同?
答案 0 :(得分:3)
使用除PerformClick()
之外的其他内容。例如form.buttonStart.Text = "This is my form";
或更改职位等......
原因是,方法PerformClick()
仅引发.NET事件Click
。但是跨线程操作的问题是使用windows-message-loop。因此,如果你想“做问题”,你必须执行一些使用windows-message-loop的行动。
答案 1 :(得分:2)
此行为由属性控制:Control.CheckForIllegalCrossThreadCalls
默认情况下,只有在附加调试器时才会出现这种情况,这就是您所看到的行为。
答案 2 :(得分:0)
任何人都可以开导我吗?单位中发生的情况如此不同 测试与本机运行表单相比?
没有什么不同。
如果您需要在Nunit上检查异常,请更好地使用Exception Asserts。否则nunit不会为您显示例外情况。
如果你没有为异常做资产,至少放一个try catch块并记录异常,你也会在测试用例中得到相同的异常。