我爲我們的WinRT應用程序創建了ref class Dispatcher
,該應用程序使用Windows::System::Threading::ThreadPool
中的線程創建消息泵基礎結構。必須繼承Dispatcher
才能使派生類具有此機制。C++/CX D'tor未調用
問題是從這個基本Dispatcher派生的每個類都不會被破壞(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);
}
};
所以,因爲這是一個引用類,當裁判數爲0的D'TOR應該被調用,但因爲我通過this
到WorkItemHandler
委託,線程持有對Dispatcher
類的引用,這會導致循環引用。因此,由於線程正在無限期地等待事件被設置,所以總是會引用一個不會調用其析構函數的類(其應該設置m_invocationHandle
事件並等待線程完成)。
我想過使用Platform::WeakReference
,但我必須把它Resolve
到Dispatcher^
以獲得m_invocationHandle
其中,因爲這不利於將提高裁判計數以及callsing WaitForSingleObject(...)
之前。
任何想法?
@HansPassant我想你錯過了c'tor創建從異步運行的線程池中的線程......這樣的C事實'tor完成 – ZivS
分成兩個對象。一個是公共調度員,它提到了「真正的」調度員。當公共調度員被破壞時,它會告訴「真正的」調度員進行清理。 –
@RaymondChen,感謝您的建議,聽起來很簡單,並保持我想要的封裝。我實際上是通過給所需成員傳遞引用來解決這個問題,而不是傳遞'this',但是你的建議聽起來更「乾淨」 – ZivS