Visual c++ 两种形式的僵局
我有两个简单的窗口在单独的线程和按钮。通过按下一个窗口中的按钮,程序将消息发送到另一个窗口,反之亦然。收到的消息使用表单名称启动消息框。通常我有死锁,当不可能按下messagebox上的按钮时。只有一种组合存在-当表格A激活时,按B表格上的按钮。为什么它会在所有其他情况下导致死锁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
#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,我不会这么做。