Вариант 1. Обработка ожидающих обратных вызовов через Application.DoEvents после удаления обработчиков событий, но перед деструктором. Обратите внимание, что в документации сказано, что это обрабатывает сообщения Windows и не упоминается, если это вызывает обработку вызовов.
Вариант 2: не блокировать поток событий: вызывать обратные вызовы формы через BeginInvoke. Обратите внимание, что вы можете получить события после уничтожения объекта C ++, поэтому добавьте дополнительную логику в обработчики событий, чтобы гарантировать, что объект C ++ не был уничтожен.
FYI, BeginInvoke
и Invoke
оба используют эту функцию. BeginInvoke
устанавливает synchronous
в ложь. Обратите внимание, что я немного взломал этот метод, чтобы удалить неинтересные части:
private object MarshaledInvoke(Control caller, Delegate method, object[] args, bool synchronous)
{
ThreadMethodEntry entry = new ThreadMethodEntry(caller, method, args, synchronous, executionContext);
lock (this.threadCallbackList)
{
if (threadCallbackMessage == 0)
threadCallbackMessage = SafeNativeMethods.RegisterWindowMessage(Application.WindowMessagesVersion + "_ThreadCallbackMessage");
this.threadCallbackList.Enqueue(entry);
}
UnsafeNativeMethods.PostMessage(new HandleRef(this, this.Handle), threadCallbackMessage, IntPtr.Zero, IntPtr.Zero);
// BeginInvoke just takes this branch instead of waiting for completion
if (!synchronous)
return entry;
if (!entry.IsCompleted)
this.WaitForWaitHandle(entry.AsyncWaitHandle);
if (entry.exception != null)
throw entry.exception;
return entry.retVal;
}