ich mit diesem ordentlichen Code aus CodeprojectEndInvoke() nicht zurück (Schleife Deadlock?)
Es ein bisschen herum nur spielen bin ist eine sichere Aufruf Methode für Kontrollen:
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);
}
Szenario 1: Windows Forms-App mit einem WebBrowser-Steuerelement. Dieser Aufruf gibt, was es soll (das zurückkehrende Ergebnis egal ist im Moment nur für die Prüfung um):
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 weit so gut, gute Arbeit vom Typ, der dieses Fragment von sicherem Aufruf erstellt.
Szenario 2: Als nächstes möchte ich einige Komponententests ausführen, die einige WebBrowser-basierte Sachen verarbeiten. Dieser kleine Test soll dies demonstrieren:
[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);
//...
}
Auf diese Weise erhalte ich einen unendlichen Aufruf SafeInvoke, genauer gesagt es endet hier:
object endResult = isi.EndInvoke(result);
Haben Sie einen Hinweis, warum der Aufruf nie endet? Ist es mehr wegen meines selbstgemachten STA-Threads? Könnte es in Verbindung mit NUnit ein Problem mit dem Console Runner sein?
Es gibt keine Nachrichtenschleife auf dem STA-Thread ('Application.Run'), die für' Invoke' Unterstützung obligatorisch ist. –
Ohhh, das scheint absolut plausibel, und natürlich ... Ich werde es morgen überprüfen und Feedback geben. Vielen Dank –
@ stev-e: Nebenbei bemerkt, ich rate immer die Verwendung von 'InvokeRequired'. Der "Safe Invoke" -Ansatz ist ein Anti-Pattern. Code sollte immer wissen, wo er läuft, und Thread-Sprünge sollten explizit sein. –