I'm just playing around a bit with this neat code from Codeproject
There is a safe invocation method for controls:
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);
}
Scenario 1: Windows Forms app with an WebBrowser control on it. This call returns what it should (the returning result is of no matter at the moment, just for testing around):
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);
}
So far so good, nice job from the guy that created this fragment of safe invocation.
Scenario 2: Next I would like to run some unit tests that handle some WebBrowser based stuff. This little test shall demonstrate this:
[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);
//...
}
This way, I get an infinite call to SafeInvoke, more precisely it ends here:
object endResult = isi.EndInvoke(result);
Do you have a hint why the invocation never ends? Is it more because of my self made STA thread? Might it be a console runner problem in combination with NUnit?