Мое приложение имеет графический интерфейс на основе ATL (CWnd, CDialog, …) и состоит из нескольких страниц (CDialog). В противном случае одна из этих страниц пуста, но имеет рамку-заполнитель (CWnd), размер которой изменяется вместе с диалогом. Все построено как x64.
Когда страница загружается, она запрашивает дескриптор элемента управления из управляемой (C #) стороны приложения, используя COM-взаимодействие, и добавляет элемент управления в диалог как CWnd, созданный из этого дескриптора:
Управляемая реализация упрощена:
// Class "ManagedControlProvider"private Control myUserControl;
public long CreateControl()
{
myUserControl = /*Create some new inheritant of UserControl */
myUserControl.Dock = DockStyle.Fill;
return myUserControl.Handle.ToInt64();
}
Родная сторона упрощена:
// Call the managed class. Lifetime of m_pManagedControlProvider
// is ensured elsewhere.
LONGLONG lHandle = m_pManagedControlProvider->CreateControl();
// m_pUserCtrlAsCWnd is CWnd*
m_pUserCtrlAsCWnd = CWnd::FromHandle((HWND)lHandle);
m_pUserCtrlAsCWnd->SetParent(this);
// m_ControlFrame is just a native helper-CWnd the dialog that
// resizes with it a so gives us the size we want to set for the
// managed control. This code is also call in every resize -event.
RECT winRect;
m_ControlFrame.GetWindowRect(&winRect);
ScreenToClient(&winRect);
m_pUserCtrlAsCWnd->SetWindowPos(NULL,
winRect.left, winRect.top, winRect.right - winRect.left,
winRect.bottom - winRect.top, 0);
Я сделал это несколько раз, и это обычно работает точно так, как должно. Но иногда, как и сейчас, я испытываю зависания приложений без какой-либо явной причины. С моим текущим контролем это, кажется, происходит примерно через 5 секунд после того, как фокус установлен на какое-то другое настольное приложение.
Я проверил, что проблема не в жизненном цикле управляемого элемента управления или GC. Кроме того, это воспроизводимо в отладочной сборке, так что оптимизации не виноваты. Когда происходит зависание, я могу подключить отладчик и увидеть, что какой-то цикл ATL продолжает работать, но это единственный фрагмент кода, который я могу видеть в стеке (imo это означает, что цикл сообщений каким-то образом попал в бесконечный цикл, не взаимодействуя с мой код).
Теперь для исправления грязи: я добавил отдельный поток в свой управляемый элемент управления, который вызывает this.Focus () каждую секунду в потоке пользовательского интерфейса. Очевидно, это нелепый хак, но он работает до тех пор, пока я приостанавливаю фокусировку каждый раз, когда пользователь открывает комбо и т. Д. (В противном случае они закрываются каждую секунду).
Что я делаю не так или что может вызвать это несколько непредсказуемое поведение?
Задача ещё не решена.
Других решений пока нет …