未调用 C++/CX D'tor

标签 c++ multithreading windows-runtime c++-cx circular-reference

我为我们的 WinRT 应用程序创建了一个 ref class Dispatcher,它使用来自 Windows::System::Threading::ThreadPool 的线程来创建某种消息泵基础设施。 Dispatcher 必须被继承,以便派生类具有此机制。

问题是派生自该基 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 委托(delegate), thread 持有对 Dispatcher 类的引用,这会导致循环引用。因此,由于线程无限等待 m_invocationHandle 事件被设置,总是有一个对 this 类的引用,它永远不会调用它的析构函数(应该设置 m_invocationHandle 事件并等待线程完成)。

我考虑过使用 Platform::WeakReference,但在调用 WaitForSingleObject( ...) 以获取 m_invocationHandle,但这并没有帮助,因为这也会增加引用计数。

有什么想法吗?

最佳答案

如果您不想添加“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
    }
}

关于未调用 C++/CX D'tor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38562241/

相关文章:

java - 混淆 Java Swing 线程中的事件顺序

c# - 如何捕获线程执行中方法返回的值#

c# - StorageFile.OpenAsync 中的 UnauthorizedAccessException

c++ - 将模板函数绑定(bind)到 gtkmm 信号时出现编译错误

c++ - 带有构造函数转发的类模板

c# - 线程问题

c# - 在 c# metro 应用程序中创建 3D 立方体

javascript - winjs appbar.wincontrol 为空

c++ - 将一串数字转换为二进制

模板中的 C++ 模板