首页 > 解决方案 > 当我的 UI 在 MFC 中获得关闭输入时,如何退出线程

问题描述

我正在用“MFC”制作一些程序。

单击 A 按钮时,消息处理程序使新线程开始工作。

在工作中,用户可以按 B 按钮退出应用程序。

在由 A 按钮制作的线程中,它使用的是我制作的 C 类。

班级动态分配一些工作资源。

当按下 B 按钮时,我想在我的应用程序死机之前取消分配资源。

我怎样才能做到这一点?请帮忙!!!:)

void CMyDlg::On_A_BnClicked() {  // do the job button
    ...
    AfxBeginThread(MyThread, (LPVOID)this);
    ...
}
UINT CMyDlg::MyThread(LPVOID arg) {
    ...
    MyCClass mcc;
    for (int i = 0; i < 100; i++) {
        ...
        mcc.init(file_name);
        mcc.do_somethin();
        mcc.deinit();
        ...
    }
    ...
}
void CMyDlg::On_B_BnClicked() {  // close button
}
void MyCClass::init(file_name) {
    mFileClass.Open(file_name, CFile::modeCreate | CFile::modeWrite);
    // and so on
    ...
}

如果用户在 MyThread 中执行“do_someth”方法时按下 B 按钮。

如何在 MyCClass 对象的 deinit() 方法之后退出 MyThread?

我想了一种在 B 按钮处理程序中创建事件,然后将消息发布到 MyCClass

这样我就可以在 MyCClass 的消息处理程序中取消所有资源。

但这似乎不起作用。:(

标签: c++multithreadingc++11stlmfc

解决方案


一般机制:您的工作线程(WT)应该有一个受保护的数据成员bool bRunning = true(默认情况下),一个Exit()设置bRunning = false. WT 循环bRunning定期检查并中止false。创建 WT 时,请保留其句柄(假设为hWT),并在应用程序退出之前调用hWT->Exit().

--

在 WT 退出时间可能较长的情况下,增加同步机制。一个例子:

// WT.h

public:

int Run();

void Exit() // ** Assume that only main-thread call this, once. **
{
    std::mutex m_dummy_mutex;
    std::unique_lock<std::mutex> guard(m_dummy_mutex);

    TRACE("WT state switched to not-running.\n");
    m_bRunning = false; // <-- (1)

    TRACE("Wait for WT stopped notification...\n");
    // (It may happen that the receiver wakes up, although no notification happened.)
    bool rv = m_stopped.wait_for(guard, std::chrono::seconds(5), // <-- (2)
               [this]() {return (m_pResource == nullptr); });
               // 'Spurious Wakeup' mitigation with lambda predicate.

    #ifdef _DEBUG
    if (rv)
        TRACE("WT stopped notification - Recieved.\n");
    else
        TRACE("WT stopped notification - Timeout expired.\n");
    #endif
}

protected:

std::condition_variable m_stopped;
bool                    m_bRunning = true; // Running until Stop().
CResource             * m_pResource = nullptr;

在 WT 循环中:

// WT.cpp

int CWT::Run()
{
    m_pResource = new CResource; // Let's say CResource is your Resource.

    while (m_bRunning)
    {
        // Do something ... (May take time. Check regularly m_bRunning to abort.)

        if (!m_bRunning)
        {
            delete m_pResource;
            m_pResource = nullptr;
            m_stopped.notify_one(); // <-- (3)
            TRACE("WT stopped. Main-thread notified.\n");
            continue;
        }
    }

    return 0;
}
  • 与其使用 new/delete,不如使用 C++ 智能指针。

推荐阅读