我为WinRT应用程序创建了一个ref class Dispatcher
,它使用来自Windows::System::Threading::ThreadPool
的线程来创建一种消息泵基础结构。必须继承Dispatcher
,以便派生类具有此机制。
问题是从这个基本Dispatcher派生的每个类都没有被破坏(不被称为)。
我解决了这个问题,我想我已经了解导致这个问题的原因,但我不知道如何解决这个问题。
以下是与此问题相关的一些代码:
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);
}
};
所以,因为这是一个ref类,当引用计数达到0时应该调用它,但是因为我将this
传递给WorkItemHandler
委托,所以该线程持有对该引用的引用Dispatcher
类,它导致循环引用。因此,由于线程无限期地等待设置m_invocationHandle
事件,所以总是会引用this
类,它永远不会调用它的析构函数(应该设置m_invocationHandle
事件和等待线程完成。)
我考虑过使用Platform::WeakReference
,但在调用Resolve
之前,我必须Dispatcher^
将其WaitForSingleObject(...)
发送到m_invocationHandle
才能获得user@host:/home/db2inst1:>db2 "select * from mytable"
VAL NEW_VAL
--- -------
5 -
6 -
A -
3 record(s) selected.
user@host:/home/db2inst1:>db2 "CREATE VIEW MYTABLEVW AS SELECT NEW_VAL,VAL FROM MYTABLE"
DB20000I The SQL command completed successfully.
user@host:/home/db2inst1:>db2 "select * from mytablevw"
NEW_VAL VAL
------- ---
- 5
- 6
- A
3 record(s) selected.
这有助于提高引用次数。
有什么想法吗?
答案 0 :(得分:0)
捕获"这个"如果您不想添加它,则作为常规指针而不是C ++ / CX指针。只需确保您的函数在析构函数完成之前结束:
Dispatcher()
{
m_invocationHandle = CreateEvent(nullptr, FALSE, FALSE, nullptr);
m_disposed = false;
IInspectable* _this = reinterpret_cast<IInspectable*>(this);
m_asyncThread = Windows::System::Threading::ThreadPool::RunAsync(
ref new Windows::System::Threading::WorkItemHandler(
[_this](Windows::Foundation::IAsyncAction^ operation)
{
reinterpret_cast<Dispatcher^>(_this)->MyLoop();
}));
}
void MyLoop()
{
while (m_disposed == false)
{
WaitForSingleObject(m_invocationHandle, INFINITE);
//copy Pending Queue to Executing Queue
//Run all handlers in Executing Queue and clear it
}
}