Możliwe, że tworzysz kontrolki w niewłaściwym wątku. Rozważ następującą dokumentację z MSDN :
Oznacza to, że InvokeRequired może zwrócić false, jeśli Invoke nie jest wymagane (wywołanie występuje w tym samym wątku) lub jeśli formant został utworzony w innym wątku, ale uchwyt kontrolki nie został jeszcze utworzony.
W przypadku, gdy uchwyt kontrolki nie został jeszcze utworzony, nie należy po prostu wywoływać właściwości, metod lub zdarzeń w kontrolce. Może to spowodować utworzenie uchwytu formantu w wątku w tle, izolowanie formantu w wątku bez pompy komunikatów i niestabilność aplikacji.
Możesz chronić się przed tym przypadkiem, sprawdzając również wartość IsHandleCreated, gdy InvokeRequired zwraca false w wątku w tle. Jeśli uchwyt sterujący nie został jeszcze utworzony, przed wywołaniem Invoke lub BeginInvoke należy poczekać, aż zostanie utworzony. Zwykle dzieje się tak tylko wtedy, gdy wątek w tle jest tworzony w konstruktorze formularza podstawowego dla aplikacji (jak w Application.Run (new MainForm ()), przed wyświetleniem formularza lub wywołaniem Application.Run.
Zobaczmy, co to oznacza dla Ciebie. (Byłoby to łatwiejsze do uzasadnienia, gdybyśmy również widzieli Twoją implementację SafeInvoke)
Zakładając, że twoja implementacja jest identyczna z tą, do której się odwołujesz, z wyjątkiem sprawdzenia przed IsHandleCreated , postępujmy zgodnie z logiką:
public static void SafeInvoke(this Control uiElement, Action updater, bool forceSynchronous)
{
if (uiElement == null)
{
throw new ArgumentNullException("uiElement");
}
if (uiElement.InvokeRequired)
{
if (forceSynchronous)
{
uiElement.Invoke((Action)delegate { SafeInvoke(uiElement, updater, forceSynchronous); });
}
else
{
uiElement.BeginInvoke((Action)delegate { SafeInvoke(uiElement, updater, forceSynchronous); });
}
}
else
{
if (uiElement.IsDisposed)
{
throw new ObjectDisposedException("Control is already disposed.");
}
updater();
}
}
Rozważmy przypadek, w którym wywołujemy SafeInvoke
z wątku innego niż GUI dla kontrolki, której uchwyt nie został utworzony.
uiElement
nie jest zerowa, więc sprawdzamy uiElement.InvokeRequired
. Zgodnie z dokumentacją MSDN (pogrubiona) InvokeRequired
zostanie zwrócona, false
ponieważ mimo że została utworzona w innym wątku, uchwyt nie został utworzony! To odsyła nas do else
stanu, w którym sprawdzamy IsDisposed
lub natychmiast przystępujemy do wywołania przesłanej akcji ... z wątku w tle !
W tym momencie wszystkie zakłady są wyłączone z re: tej kontroli, ponieważ jej uchwyt został utworzony w wątku, który nie ma dla niej pompy komunikatów, jak wspomniano w drugim akapicie. Być może jest to przypadek, z którym się spotykasz?