C++ C++/CX D';tor未呼叫

C++ C++/CX D';tor未呼叫,c++,multithreading,windows-runtime,c++-cx,circular-reference,C++,Multithreading,Windows Runtime,C++ Cx,Circular Reference,我为我们的WinRT应用程序创建了一个ref类调度程序,它使用Windows::System::Threading::ThreadPool中的一个线程来创建某种消息泵基础结构。必须继承调度程序,才能使派生类具有此机制 问题是,从这个基本调度器派生的每个类都没有被破坏(没有调用D'tor) 我隔离了这个问题,我想我已经了解了这个问题的原因,但我不确定如何解决这个问题 以下是与此问题相关的一些代码: public delegate void FunctionDelegate(); ref class

我为我们的WinRT应用程序创建了一个
ref类调度程序
,它使用
Windows::System::Threading::ThreadPool
中的一个线程来创建某种消息泵基础结构。必须继承
调度程序
,才能使派生类具有此机制

问题是,从这个基本调度器派生的每个类都没有被破坏(没有调用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);
    }
};
因此,由于这是一个ref类,当ref计数达到0时应该调用它的d'tor,但由于我将
this
传递给
WorkItemHandler
委托,因此线程持有对
Dispatcher
类的引用,这会导致循环引用。因此,由于线程无限期地等待
m_invocationHandle
事件的设置,因此始终存在对
this
类的引用,该类永远不会调用其析构函数(该类应设置
m_invocationHandle
事件并等待线程完成)

我曾考虑过使用
Platform::WeakReference
,但在调用
WaitForSingleObject(…)
之前,我必须
将其解析为
Dispatcher^
,以获得
m\u调用句柄,这也会增加ref计数,因此毫无帮助

有什么想法吗?

如果不想添加“this”,请将其捕获为常规指针,而不是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
    }
}
Dispatcher()
{   
m_invocationHandle=CreateEvent(nullptr,FALSE,FALSE,nullptr);
m_=false;
IInspectable*_this=重新解释铸件(this);
m_asyncThread=Windows::System::Threading::ThreadPool::RunAsync(
ref新Windows::System::Threading::WorkItemHandler(
[_this](Windows::Foundation::IAsyncation^操作)
{
重新解释cast(_this)->MyLoop();
}));
}
void MyLoop()
{
while(m_=false)
{
WaitForSingleObject(m_调用句柄,无限);
//将挂起队列复制到执行队列
//运行执行队列中的所有处理程序并将其清除
}
}
如果不希望添加“this”,则将其捕获为常规指针,而不是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
    }
}
Dispatcher()
{   
m_invocationHandle=CreateEvent(nullptr,FALSE,FALSE,nullptr);
m_=false;
IInspectable*_this=重新解释铸件(this);
m_asyncThread=Windows::System::Threading::ThreadPool::RunAsync(
ref新Windows::System::Threading::WorkItemHandler(
[_this](Windows::Foundation::IAsyncation^操作)
{
重新解释cast(_this)->MyLoop();
}));
}
void MyLoop()
{
while(m_=false)
{
WaitForSingleObject(m_调用句柄,无限);
//将挂起队列复制到执行队列
//运行执行队列中的所有处理程序并将其清除
}
}

@HansPassant我认为您忽略了这样一个事实,即c'tor从异步运行的线程池中创建了一个线程……因此c'tor确实完全分解为两个对象。一个是公共调度器,它引用了“真实”的调度器。当公共调度器被破坏时,它会告诉“真正的”调度器清理。@RaymondChen,谢谢你的建议,听起来很简单,并保留了我想要的封装。实际上,我通过将引用传递给所需的成员而不是传递
this
,解决了这个问题,但是您的建议听起来“更干净”@HansPassant我认为您忽略了这样一个事实,即c'tor从线程池创建了一个线程,该线程池异步运行……因此c'tor确实完全拆分为两个对象。一个是公共调度器,它引用了“真实”的调度器。当公共调度器被破坏时,它会告诉“真正的”调度器清理。@RaymondChen,谢谢你的建议,听起来很简单,并保留了我想要的封装。实际上,我通过将引用传递给所需的成员而不是传递
this
,解决了这个问题,但是你的建议听起来“更干净”嗯,不。lambda在破坏时会释放
this
,现在你有了一个双释放bug。嗯,不。lambda在破坏时会释放
this
,现在你有了一个双重版本的bug。