multithreading - 在 MFC 中同时挂起 2 个线程的问题!

标签 multithreading mfc

我正在学习线程和多线程..所以我刚刚创建了一个小应用程序,我将在其中更新
进度条和使用线程的静态文本。我从用户那里得到两个输入,开始值和结束值
循环应该旋转多长时间。我的应用程序中有 2 个线程。

Thread1-更新进度条(根据循环)将显示计数(循环计数)的静态文本。
Thread2 - 更新另一个仅显示名称的静态文本

基本上,如果用户单击开始,进度条会增加,同时文件计数和名称会并行显示。
还有另一个操作,如果用户点击暂停,它(线程)必须暂停,直到用户点击恢复。
问题是,以上对于两个线程都不起作用(不会挂起和恢复)..但适用于单线程。
请检查代码以获得想法并回复我可以做什么!

在按钮上单击开始

void CThreadingEx3Dlg::OnBnClickedStart()
{
    m_ProgressBar.SetRange(start,end);
    myThread1 = AfxBeginThread((AFX_THREADPROC)MyThreadFunction1,this);
    myThread2 = AfxBeginThread((AFX_THREADPROC)MyThreadFunction2,this);
}

线程1
UINT MyThreadFunction1(LPARAM lparam)
{
    CThreadingEx3Dlg* pthis = (CThreadingEx3Dlg*)lparam;
    for(int intvalue =pthis->start;intvalue<=pthis->end; ++intvalue)
    {
        pthis->SendMessage(WM_MY_THREAD_MESSAGE1,intvalue);
    }
    return 0;
}

线程1函数
LRESULT CThreadingEx3Dlg::OnThreadMessage1(WPARAM wparam,LPARAM lparam)
{
    int nProgress= (int)wparam;
     m_ProgressBar.SetPos(nProgress);
       CString strStatus;
    strStatus.Format(L"Thread1:Processing item: %d", nProgress);
        m_Static.SetWindowText(strStatus);
    Sleep(100);
    return 0;
}

线程2
UINT MyThreadFunction2(LPARAM  lparam)
{
    CThreadingEx3Dlg* pthis = (CThreadingEx3Dlg*)lparam;
    for(int i =pthis->start;i<=pthis->end;i++)
    {
        pthis->SendMessage(WM_MY_THREAD_MESSAGE2,i);
    }
    return 0;
}

线程2函数
LRESULT CThreadingEx3Dlg::OnThreadMessage2(WPARAM wparam,LPARAM lparam)
{
        m_Static1.GetDlgItem(IDC_STATIC6);
        m_Static1.SetWindowTextW(L"Thread2 Running");
        Sleep(100);
        m_Static1.SetWindowTextW(L"");
        Sleep(100);
        return TRUE;

}

void CThreadingEx3Dlg::OnBnClickedPause()
{
    // TODO: Add your control notification handler code here
    if(!m_Track)
    {
        m_Track = TRUE;
        GetDlgItem(IDCANCEL)->SetWindowTextW(L"Resume");
        myThread1->SuspendThread();
        WaitForSingleObject(myThread1->m_hThread,INFINITE);
        myThread2->SuspendThread();
        m_Static.SetWindowTextW(L"Paused..");

    }
    else
    {
        m_Track = FALSE;
        GetDlgItem(IDCANCEL)->SetWindowTextW(L"Pause");
        myThread1->ResumeThread();
        myThread2->ResumeThread();

        /*myEventHandler.SetEvent();
        WaitForSingleObject(myThread1->m_hThread,INFINITE);*/
    }
}

最佳答案

我想我应该将评论中的一些讨论总结成一个答案。

在 Windows 编程中,您永远不应该尝试从后台线程操作 GUI 控件,因为这样做会导致您的程序死锁。这意味着只有主线程应该接触 GUI 的元素。 (从技术上讲,重要的是哪个线程创建了控件,但在后台线程中创建控件并不常见)。

此要求在 Joe Newcomer's article on worker threads 中有详细说明(请参阅“工作线程和 GUI II:不要触摸 GUI”)。

您正在使用 SendMessage在你的线程程序中。这会导致调用目标控件的适当消息处理程序,但在调用 SendMessage 的线程中。 .在您的情况下,这意味着后台线程运行消息处理程序,因此更新进度条和标签。

另一种方法是使用 PostMessage .这会导致消息被添加到队列中以由主线程的消息循环处理。当主线程开始运行时,它会按照消息添加到队列中的顺序处理消息,并调用消息处理程序本身。由于主线程拥有窗口,因此更新控件是安全的。

您还应该注意 SuspendThreadResumeThread很难做到正确。您可能想阅读 this section Joe Newcomer 的文章,其中描述了一些危险。

使用 timer 通常可以更好地完成此类任务。 .这是一种让操作系统在特定时间过去后通知您的程序的机制。您可以使用如下计时器来实现它:

BEGIN_MESSAGE_MAP(CThreadingEx3Dlg, CDialog)
   ON_WM_DESTROY()
   ON_WM_TIMER()
END_MESSAGE_MAP()

void CThreadingEx3Dlg::OnTimer(UINT_PTR nTimerID)
{
   static int progress = 0;
   if (nTimerID == 1)
   {
      m_ProgressBar.SetPos(progress);
      CString strStatus;
      strStatus.Format(_T("Processing item: %d"), progress);
      m_Static.SetWindowText(strStatus);
      progress++;
      if (progress > end) // If we've reached the end of the updates.
         KillTimer(1);
   }
}

BOOL CThreadingEx3Dlg::OnInitDialog()
{
   // ... initialize controls, etc, as necessary.
   SetTimer(1, 100, 0);
}

void CThreadingEx3Dlg::OnDestroy()
{
   KillTimer(1);
}

如果您希望同时处理两个更新,它们可以使用相同的计时器。如果它们需要在不同的时间发生(例如一个间隔为 100 毫秒,另一个间隔为 150 毫秒),那么您可以调用 SetTimer两次使用不同的ID。要暂停操作,请调用 KillTimer .要恢复它,请调用 SetTimer再次。

关于multithreading - 在 MFC 中同时挂起 2 个线程的问题!,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2736749/

相关文章:

java - 多线程应用程序性能

c# - WinForms 中的数据绑定(bind)执行异步数据导入

visual-studio-2008 - 在 Visual Studio 调试器中中断按钮单击事件

c++ - 创建全局变量导致链接器错误

c++ - MFC:以编程方式控制 TAB 顺序

python - Python 和 PyQt 中的线程错误

c - sigwait后如何执行语句

C#.Net - 线程在一个循环中抓取相同的文件

c++ - 如何使用 XML 文件中的数据填充 MFC 中的列表框?

c++ - MFC显示透明背景的png