Можливо, ви створюєте елементи керування на неправильній нитці. Розгляньте наступну документацію від MSDN :
Це означає, що InvokeRequired може повернути false, якщо Invoke не потрібно (виклик відбувається в тому ж потоці), або якщо елемент керування був створений в іншому потоці, але дескриптор елемента керування ще не створений.
У випадку, коли дескриптор елемента управління ще не створений, не слід просто викликати властивості, методи або події на елементі управління. Це може спричинити створення дескриптора елемента керування у фоновому потоці, ізолюючи елемент керування для потоку без насоса повідомлення та роблячи програму нестабільною.
Ви можете захиститися від цього випадку, також перевіривши значення IsHandleCreated, коли InvokeRequired повертає false у фоновому потоці. Якщо дескриптор управління ще не створений, перед викликом Invoke або BeginInvoke потрібно почекати, поки він буде створений. Як правило, це відбувається лише в тому випадку, якщо фоновий потік створений у конструкторі первинної форми для програми (як у Application.Run (new MainForm ()), перш ніж форма буде показана або викликано Application.Run.
Давайте подивимось, що це означає для вас. (Це було б простіше міркувати про те, якби ми бачили і вашу реалізацію SafeInvoke)
Припускаючи, що ваша реалізація ідентична вказаній , за винятком перевірки щодо IsHandleCreated , давайте слідуватимемо логіці:
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();
}
}
Розглянемо випадок, коли ми телефонуємо SafeInvoke
з потоку, не пов’язаного з графічним інтерфейсом, для елемента керування, дескриптор якого не створений.
uiElement
не є нульовим, тому ми перевіряємо uiElement.InvokeRequired
. Відповідно, MSDN-документи (напівжирним шрифтом) InvokeRequired
повертаються, false
оскільки, хоча вони були створені в іншому потоці, дескриптор не створений! Це спрямовує нас до else
умови, коли ми перевіряємо IsDisposed
або негайно приступаємо до виклику надісланої дії ... з фонового потоку !
На цьому етапі всі ставки відключені: цей контроль, оскільки його дескриптор створений на потоці, який не має насоса для повідомлення, як зазначено у другому абзаці. Можливо, це випадок, з яким ви стикаєтесь?