死锁有两种形式

时间:2014-10-21 15:13:55

标签: visual-c++ mfc

我在带有按钮的单独线程上有两个简单的窗口。通过在一个窗口中按下按钮程序将消息发送到另一个窗口,反之亦然。收到的消息启动消息框与表单名称。通常我有死锁,当无法按下消息框上的按钮时。只存在一种组合 - 当表格A处于活动状态时按下B表格上的按钮。为什么它会在所有其他情况下导致死锁?

#include <afxwin.h>
#include <iostream>
class MyWnd;

extern MyWnd *Bwnd;
extern MyWnd *Awnd;
#define IDC_BTN       100
using namespace std;
class MyWnd :public CFrameWnd
{
public:
    CButton m_wndPushButton;
    MyWnd(const wchar_t * txt  )
    {

        Create(NULL,txt);
    }


    afx_msg LRESULT OnMessageCust(WPARAM wParam, LPARAM lParam)
    {
        wchar_t* p = new wchar_t[20];

        this->GetWindowText(p,20);
        AfxMessageBox(p);

        delete(p);

    return 0;
    }


    afx_msg void OnPushButtonClicked ()
    {
        //SendMessage(WM_USER + 1, 0, 0);
        if (this==Bwnd) { TRACE("Awnd"); Awnd->SendMessage(WM_USER + 1, 0, 0) ; }
        if (this==Awnd) {TRACE("Bwnd"); Bwnd->SendMessage(WM_USER + 1, 0, 0);}

        //AfxMessageBox(L"Hello");
    } ;

    afx_msg  int OnCreate (LPCREATESTRUCT lpcs)  {

        if (CWnd::OnCreate (lpcs) == -1)   return -1;   

        CRect rectbutton(50,50,150,150); 

        m_wndPushButton.Create (_T ("Start"), WS_CHILD | WS_VISIBLE |  BS_PUSHBUTTON, rectbutton, this, IDC_BTN);

        return 0;  

    } ;

    DECLARE_MESSAGE_MAP ()

};

BEGIN_MESSAGE_MAP (MyWnd, CFrameWnd)
    ON_WM_CREATE ()   
    ON_BN_CLICKED (IDC_BTN, OnPushButtonClicked)  
    ON_MESSAGE(WM_USER + 1 ,OnMessageCust)

    ON_WM_PAINT ()
    ON_WM_DESTROY()
END_MESSAGE_MAP ()



MyWnd *Bwnd;
MyWnd *Awnd;


class modHolder : public CWinThread
{
    DECLARE_DYNCREATE(modHolder)

protected:
    modHolder()
    {

    };           
    virtual ~modHolder()
    {

    };

public:
//MyWnd *Bwnd;  
    virtual BOOL InitInstance()
        {

            Bwnd = new MyWnd(L"B window");

            ShowWindow (Bwnd->m_hWnd,SW_SHOW);
            Bwnd->UpdateWindow();
            return true;
        };
    virtual int ExitInstance()
        {
            delete(Bwnd);
            return CWinThread::ExitInstance();
        };

protected:
    DECLARE_MESSAGE_MAP()
};

BEGIN_MESSAGE_MAP(modHolder, CWinThread)
END_MESSAGE_MAP()

IMPLEMENT_DYNCREATE(modHolder, CWinThread)



class MyApp :public CWinApp
{
    //MyWnd *Awnd; 
public:
    BOOL InitInstance()
    {
        Awnd = new MyWnd(L"A window");

        m_pMainWnd = Awnd;
        m_pMainWnd->ShowWindow(SW_SHOW);

        CWinThread* pThread= AfxBeginThread( RUNTIME_CLASS(modHolder) );


        return TRUE;
    }
};



MyApp theApp ;

1 个答案:

答案 0 :(得分:0)

原因很简单:你没有在第二个帖子中使用m_pMainFrame。

会发生什么:

  1. 点击MyApp主题中的按钮。
  2. 邮件将发送到第二个窗口。
  3. 当前的MyApp线程暂停,直到第二个线程返回。
  4. 在第二个modHolder线程中。消息循环接收消息。
  5. 调用您的处理程序并启动AfxMessageBox。
  6. AfxMessageBox的内部代码现在尝试获取父窗口。没有人为这个线程设置父窗口,通常使用CWinThread :: m_pMainWnd。
  7. 您的应用程序最终使用CWinApp m_pMainFrame,这是当前被阻止的窗口A?
  8. 消息框例程尝试禁用窗口(导致另一个SendMessage到达)
  9. 死锁:窗口A等待窗口B,窗口B等待窗口A的反应
  10. 这就是为什么必须非常仔细地设计两个UI线程的原因。一个新手应该完全避免它。

    顺便说一下:即使对于测试代码,你的代码也很糟糕。了解更多基础知识。 i.E:当你可以使用CString和GetWindowText时,为什么要用new分配存储?