Я создал ref class Dispatcher
для нашего приложения WinRT, которое использует поток от Windows::System::Threading::ThreadPool
для создания своего рода инфраструктуры сообщений. Dispatcher
должен быть унаследован для того, чтобы производный класс имел этот механизм.C++/CX D'tor не называется
Проблема в том, что каждый класс, полученный из этой базы Диспетчер, не разрушается (D'tor не называется).
Я выделил проблему, и я думаю, что у меня есть понимание того, что вызывает эту проблему, но я не знаю, как это решить.
Вот некоторые из кода, который имеет отношение к вопросу:
public delegate void FunctionDelegate();
ref class Dispatcher
{
protected private:
Dispatcher()
{
m_invocationHandle = CreateEvent(nullptr, FALSE, FALSE, nullptr);
m_disposed = false;
m_asyncThread = Windows::System::Threading::ThreadPool::RunAsync(
ref new Windows::System::Threading::WorkItemHandler(
[this](Windows::Foundation::IAsyncAction^ operation)
{
while (m_disposed == false)
{
WaitForSingleObject(m_invocationHandle, INFINITE);
//copy Pending Queue to Executing Queue
//Run all handlers in Executing Queue and clear it
}
}));
}
public:
virtual ~Dispatcher()
{
m_disposed = true;
SetEvent(m_invocationHandle);
JoinInvocationThread();
CleanUp(); //close handles etc...
}
void BeginInvoke(FunctionDelegate^ function)
{
PendingQueue->Append(function);
SetEvent(m_invocationHandle);
}
};
Так, так как это класс исх его d'тор должен быть вызван, когда счетчик ссылок достигает 0, но так как я прохожу this
к делегат WorkItemHandler
, поток содержит ссылку на класс Dispatcher
, который вызывает круговую ссылку. Таким образом, поскольку поток бесконечно ждет события m_invocationHandle
, которое всегда задается, всегда ссылается на класс this
, который никогда не вызовет его деструктор (который должен установить событие m_invocationHandle
и ждать завершения потока).
Я думал об использовании Platform::WeakReference
, но я должен буду Resolve
его к Dispatcher^
перед тем callsing WaitForSingleObject(...)
для того, чтобы получить m_invocationHandle
, который не помогает, так как это повысит кол-реф, а также.
Любые идеи?
@HansPassant Я думаю, вы пропустили тот факт, что c'tor создает поток из пула потоков, который работает асинхронно ... таким образом, гр 'tor завершает – ZivS
Разделить на два объекта. Один из них - публичный диспетчер, который имеет ссылку на «реального» диспетчера. Когда общественный диспетчер разрушен, он сообщает «реальному» диспетчеру очистить. –
@ RaymondChen, спасибо за предложение, звучит просто и поддерживает инкапсуляцию, которую я хотел. Я на самом деле решил это, передав ссылки на требуемые члены вместо того, чтобы передавать 'this', но ваши предложения звучат« чище » – ZivS