Visual c++ 两种形式的僵局

Visual c++ 两种形式的僵局,visual-c++,mfc,Visual C++,Mfc,我有两个简单的窗口在单独的线程和按钮。通过按下一个窗口中的按钮,程序将消息发送到另一个窗口,反之亦然。收到的消息使用表单名称启动消息框。通常我有死锁,当不可能按下messagebox上的按钮时。只有一种组合存在-当表格A激活时,按B表格上的按钮。为什么它会在所有其他情况下导致死锁 #include <afxwin.h> #include <iostream> class MyWnd; extern MyWnd *Bwnd; extern MyWnd *Awnd; #de

我有两个简单的窗口在单独的线程和按钮。通过按下一个窗口中的按钮,程序将消息发送到另一个窗口,反之亦然。收到的消息使用表单名称启动消息框。通常我有死锁,当不可能按下messagebox上的按钮时。只有一种组合存在-当表格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 ;

原因很简单:在第二个线程中没有使用m_pMainFrame

发生了什么:

单击MyApp线程中的按钮。 消息被发送到第二个窗口。 当前MyApp线程将挂起,直到第二个线程返回。 在第二个modHolder螺纹中。消息由消息循环接收。 您的处理程序将被调用并启动AfxMessageBox。 AfxMessageBox的内部代码现在尝试获取父窗口。没有人为此线程设置父窗口,通常使用CWinThread::m_pMainWnd。 您的应用程序最终使用了CWinApp m_pmainrame,这是当前被阻止的窗口a? MessageBox例程尝试禁用导致另一条SendMessage被禁用的窗口 死锁:窗口A等待窗口B,窗口B等待窗口A的反应 这就是为什么必须非常仔细地设计两个UI线程的原因。新手应该避免这样做


顺便说一句:你的代码是可怕的,即使是测试代码。了解更多基础知识。i、 E:既然可以使用CString和GetWindowText,为什么还要用new分配存储空间?

在不同的线程中使用UI通常是个坏主意。我同意这一点,但从教育的角度来看,这段代码有什么具体的错误?教育方面:这段代码几乎没有任何正确的地方。运算符new[]需要使用delete[]进行清理。自定义消息从WM_应用程序开始;WM_USER+1是为窗口类的作者保留的。为GetWindowText的调用设置20个字符的任意限制是有问题的,这违反了零一无限规则。也许你应该先学习Windows API和C++,然后再转到多线程。一旦您熟悉了这三个方面,您可以尝试编写一个多线程GUI,我不会这么做。