我在最近的项目中发现个问题,我要load一个文件,而这个load的过程可能需要很长时间,因为load过程中包括了dll的加载,界面的创建(不同的文件可能加载不同的dll,创建不同子窗口,产生不同界面),因此这个load过程只能由主界面的线程去做了,这样的话主界面就会暂时失去响应,但一个优秀的程序不应该如此。所以我想弹出一个模态对话框来提示用户“Please Wait...”,模态对话框也能暂时阻止了用户对主界面的操作,但模态对话框如果不返回,就相当于阻挡了主界面线程进一步执行load操作了,所以必须要用多线程,由于load过程必须由主界面线程执行(原因前面说了),那么我只能创建一个新的线程,由这个线程创建一个主界面的模态对话框,当主界面线程执行完load动作之后,向这个对话框发一个消息,告诉它可以EndDialog了,这样应该是没问题了吧……你们认为呢?
可实际的情况可能是这个模态对话框根本show不出来,整个过程可以这么描述:主界面的线程调用CreateThread,新线程的Run函数如下:
DWORD WINAPI ThreadDialogWait(LPVOID lpParameter)
{
return DialogBox(hInst, MAKEINTRESOURCE(IDD_PLEASE_WAIT), g_hwndMain, (DLGPROC)WaitDlgProc);
}
非常简单,(其中hInst和g_hwndMain是全局的)后来我想那是因为对话框弹出的时候,主窗口是没响应的,它在忙load动作,可能对话框弹出时候发给主窗口的一些消息没有得到返回,所以导致了对话框线程也是处于堵塞状态,show不出来。OK,我现在就用一些手段了,改进改进。
我让主窗口线程不要在CreateThread之后立即往下执行,而是等待对话框Post给自己的一个消息,才继续往下,而这个时候对话框已经show出来了,因为我可以确保对话框在post这个消息的时候,自己已经show出来了。
LRESULT CALLBACK WaitDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
SetTimer(hwndDlg, 1, 500, NULL);
SetTimer(hwndDlg, 2, 300, NULL);
g_hwndWaitDlg = hwndDlg;
break;
case WM_USER_END_DIALOG:
EndDialog(hwndDlg, 0);
break;
case WM_TIMER:
if(wParam==1)
{
PostMessage(g_hwndMain, WM_USER_MAIN_WORK, NULL, NULL);
KillTimer(hwndDlg, 1);
}
if(wParam==2)
OutputDebugString(TEXT("|"));
break;
}
return FALSE;
}
Timer1就是起到这个作用,让对话框完全show出来,才让主窗口执行下一步的load动作,(如果在WM_INITDIALOG中post这个消息,可能还是会有问题,对话框show不出),可能你注意到了,我搞了两个Timer,Timer2起啥作用?这就是我的问题了,按照这种做法,对话框是show出来了,可通过timer2很容易就观察到,在主窗口load过程中,界面还是处于无响应状态,这就不符合我的设计初衷了,这是为什么?