Ich habe ein Formular mit meinen benutzerdefinierten Steuerelementen darin.
Ich habe eine Methode in meinem Formular:
private void SetEnabledOnControls(bool val)
{
if (InvokeRequired)
{
Invoke((Action<bool>)SetEnabledOnControls, val);
}
else
{
//do the work - iterate over child controls,
//and they iterate over their children, etc...
}
}
Und innerhalb der Methoden, die sich auf der else
Zweig erhalte ich die erwähnte Ausnahme:
Cross-thread operation not valid: Control 'txtNumber' accessed from a thread other than the thread it was created on.
Mein Szenario ist eigentlich etwas komplizierter - ich habe es nur als Beispiel extrapoliert. Was eigentlich los ist, ist, dass ich WorkflowFoundation verwende - ich habe StateMachineActivity (CTP1), die in WorkflowApplication läuft (die in ihrem eigenen Thread läuft), ich habe ihr Ereignis abonniert, und von dort rufe ich SetEnabledOnControls
. Außerdem verwende ich Lesezeichen, um meinen Arbeitsablauf fortzusetzen (und außerdem gibt es MEF auf der Seite, die nicht in das Szenario eingebunden ist).
All das ist irrelevant für mein offensichtliches Missverständnis der InvokeRequired - wie ist es möglich, dass, wenn die InvokeRequired falsch ist, ich Cross-Threaded-Ausnahme haben? Ich habe keine der Steuerelemente "manuell" erstellen - es ist alles da in der Initialize() platziert von Designer.
Kann jemand etwas Licht in diese Angelegenheit bringen?
Danke!
エディテージ Mit GWLlosa Vorschlag, habe ich die ThreadId mit System.Threading.Thread.CurrentThread.ManagedThreadId
. Jetzt kommt der seltsame Teil... die Thread-ID in Initialize() ist 10. Zwischen der Übergabe der ersten 2 Zustände kommt er mit der Id 13 herein - InvokeRequired war wahr, und er wurde korrekt aufgerufen. ABER, nach dem zweiten Zustand, wenn er in SetEnabledOnControls
Es ist wieder 13, aber diesmal ist InvokeRequired falsch! Wie kann das sein!? Später gelingt es natürlich nicht, untergeordnete Steuerelemente zu ändern (nicht überraschend). Könnte es sein, dass das Formular irgendwie den Thread geändert hat, in dem es sich befindet?
EDIT 2 Jetzt rufe ich mit an:
if (IsHandleCreated)
{
Invoke((Action<bool>)SetEnabledOnControls, val);
}
und sie hat IsHandleCreated
auf true gesetzt, scheitert aber immer noch mit dem, was devSpeed gerichtet auf .
EDIT 3 FACEPALM :) Eine der Schaltflächen, die den Zustand wiederherstellten, war zunächst CancelButton für das Formular. Wenn es aus der Eigenschaft als solche entfernt wurde, hatte der Codebihind noch die DialogResult=Cancel für sie - so mein Formular war in der Tat schließen, und natürlich war es das Handle fehlt, so dass die InvokeRequired nicht richtige Informationen zurückgeben, und daher die Fehler.
Vielen Dank an alle! Ich habe heute eine neue Sache gelernt :)