我只是在玩一些来自Codeproject的简洁代码
控件有一个安全的调用方法:
public static TResult SafeInvoke<T, TResult>(this T isi, Func<T, TResult> call) where T : ISynchronizeInvoke
{
if (isi.InvokeRequired) {
IAsyncResult result = isi.BeginInvoke(call, new object[] { isi });
object endResult = isi.EndInvoke(result); return (TResult)endResult;
}
else
return call(isi);
}
场景 1:带有 WebBrowser 控件的 Windows 窗体应用程序。这个调用返回它应该返回的结果(返回的结果暂时不管,只是为了测试):
private void button1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(StartStuff));
thread.Start();
}
private void StartStuff()
{
var document = webBrowser1.SafeInvoke(o => o.Document);
}
到目前为止,创建这个安全调用片段的人做得很好,做得很好。
场景 2:接下来我想运行一些单元测试来处理一些基于 WebBrowser 的东西。这个小测试将证明这一点:
[Test, Category("Thread Safety")]
public void TestIfThreadRaisesException()
{
/* create STA thread where the browser will live and die in */
Thread thread = new Thread(RunSTAContent);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
}
private static void RunSTAContent()
{ /* simulate cross thread access to control */
var stdBrowser = new System.Windows.Forms.WebBrowser();
Task.Run(async () => await RunUnProblematicContent(stdBrowser)).Wait();
}
private static async Task RunUnProblematicContent(System.Windows.Forms.WebBrowser browser)
{
await Task.Delay(1000);
var doc = browser.SafeInvoke(o => o.Document);
//...
}
这样,我就可以无限调用 SafeInvoke,更准确地说,它在此处结束:
object endResult = isi.EndInvoke(result);
你有暗示为什么调用永远不会结束吗?是不是因为我自制的 STA 线程?可能是与 NUnit 结合使用的控制台运行程序问题?