многопоточность — C ++ / CX не вызывается

Я создал ref class Dispatcher для нашего приложения WinRT, которое использует поток из 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);
}
};

Итак, так как это класс ref, его d’tor должен вызываться, когда счетчик ссылок достигает 0, но так как я передаю this к WorkItemHandler делегат, поток содержит ссылку на Dispatcher класс, который вызывает циклическую ссылку. Таким образом, поскольку поток бесконечно ждет m_invocationHandle событие, которое будет установлено, всегда есть ссылка на this класс, который никогда не будет вызывать свой деструктор (который должен установить m_invocationHandle событие и ждать завершения потока).

Я думал об использовании Platform::WeakReference но мне придется Resolve это к Dispatcher^ перед звонком WaitForSingleObject(...) для того, чтобы получить m_invocationHandle что не помогает, так как это также увеличит количество ссылок.

Есть идеи?

1

Решение

Захватывайте «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
}
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector