Приложение зависает при хостинге управляемого управления как CWnd - PullRequest
0 голосов
/ 21 сентября 2018

Мое приложение имеет графический интерфейс на основе 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 () каждую секунду в потоке пользовательского интерфейса.Очевидно, это нелепый хак, но он работает до тех пор, пока я приостанавливаю фокусировку каждый раз, когда пользователь открывает комбо и т. Д. (Иначе они закрываются каждую секунду).

Что я делаю не так или что может вызвать это несколько непредсказуемое поведение?

...