我有一个单文档界面(SDI)Microsoft基础类(MFC)应用程序,必须加载一个大文档文件(大约需要2分钟)。出于这个原因,我打开文档时,我的应用程序仍然没有响应。
但是,我希望我的应用在打开文档时能够快速响应。问题是,如果我尝试在线程上加载我的文档,我的OnopenDocument
函数(在我的文档中)将在我实际打开文档之前返回:
BOOL CmodguiDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
start_tread(_open_doc); // just an example
return TRUE; // Will return before the document will actually be open
}
我怎样才能做到非锁定但只在文档实际打开后返回?或者我如何在加载文档时至少使我的应用程序响应?
由于
答案 0 :(得分:6)
创建线程后返回是OK。您应该为文档定义状态,例如loading
和loaded
。启动线程时,状态应为loading
。视图应该查看状态并相应地显示。当线程完成加载文档时,它应该向文档发送一条消息。在处理程序中,将状态设置为loaded
并调用UpdateAllViews()
以使视图有机会使用新文档数据进行更新。
示例:这将打印" loading"当文档正在加载和加载时#34;并在视图中完成后加载。
在resource.h中:
#define IDD_NotifyDocumentFinished 101
在文件标题中:
public:
enum DocState
{
None,
Failed,
Loading,
Loaded
};
DocState GetDocState() const {return m_state;}
private:
DocState m_state;
void StartLoading();
在文件实施中:
BOOL CMFCDocViewAsyncDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
if(!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
m_state = Loading;
StartLoading();
return TRUE;
}
UINT LongRunningFunction(LPVOID param)
{
Sleep(3000);
HWND hWnd = AfxGetApp()->m_pMainWnd->GetSafeHwnd();
NMHDR hdr = {hWnd, IDD_NotifyDocumentFinished, 0};
::SendMessage(hWnd, WM_NOTIFY, 0, reinterpret_cast<LPARAM>(&hdr));
return 0;
}
void CMFCDocViewAsyncDoc::StartLoading()
{
AfxBeginThread(&LongRunningFunction, nullptr);
}
BOOL CMFCDocViewAsyncDoc::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
if(HIWORD(nCode) == WM_NOTIFY)
{
WORD wCode = LOWORD(nCode);
AFX_NOTIFY * notify = reinterpret_cast<AFX_NOTIFY*>(pExtra);
if(notify->pNMHDR->idFrom == IDD_NotifyDocumentFinished)
{
m_state = Loaded;
UpdateAllViews(nullptr);
}
}
return TRUE;
}
在视图中:
void CMFCDocViewAsyncView::OnDraw(CDC* pDC)
{
CMFCDocViewAsyncDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
CMFCDocViewAsyncDoc::DocState state = pDoc->GetDocState();
CString sstate;
switch(state)
{
case CMFCDocViewAsyncDoc::None:
sstate = "None";
break;
case CMFCDocViewAsyncDoc::Failed:
sstate = "Failed";
break;
case CMFCDocViewAsyncDoc::Loading:
sstate = "Loading";
break;
case CMFCDocViewAsyncDoc::Loaded:
sstate = "Loaded";
break;
}
pDC->TextOut(50, 50, sstate);
}
更新:此处还可以查看类似的,更详细的示例http://www.codeproject.com/Articles/14706/Notifying-the-Document。
答案 1 :(得分:1)
当需要两分钟才能加载某些东西时,有两个原因: