使用 cURL 时 MFC 无模式对话框冻结
MFC modeless dialog freezes when using cURL
我有一个 MFC 应用程序,它尝试使用 cURL 获取页面。当 运行 应用程序时,对话框会暂时无响应。有什么办法可以解决这个问题吗?
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
static std::string GetPage(const char* url)
{
CURL *curl;
CURLcode res;
std::string page;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &page);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
return page;
}
InitInstance():
CWinApp::InitInstance();
CEpicDlg dlg;
m_pMainWnd = &dlg;
dlg.Create(IDD_MAIN);
dlg.ShowWindow(SW_SHOW);
GetPage("http://example.com/page");
dlg.RunModalLoop(MLF_NOIDLEMSG);
如前所述,您必须 运行 单独的工作线程中的函数。
CreateThread
+ WaitForSingleObject
可能表现得像一个阻塞函数,这取决于它是如何实现的...
一种替代方法是 运行 工作线程并在 GUI 线程中继续。工作线程完成后,使用同步对象让 GUI 线程了解状态。或者使用 PostMessage
通知 GUI 线程工作线程完成。确保 url 字符串数据不会在没有同步的情况下同时在两个线程之间共享...
注意,使用CDialog::DoModal
并初始化OnInitDialog
中的数据。您可能还想覆盖 OnCancel
以在退出 window.
之前正确清理
#define WM_USER1 (WM_USER + 1)
DWORD WINAPI thread_proc(LPVOID ptr)
{
//simulate a blocking function (don't put Sleep in final code)
Sleep(2000);
HWND hwnd = (HWND)ptr;
if(IsWindow(hwnd)) PostMessage(hwnd, WM_USER1, 0, 0);
return 0;
}
class CMyDialog : public CDialog
{
public:
CMyDialog(int id, CWnd* wnd) : CDialog(id, wnd) {}
BOOL OnInitDialog()
{
CDialog::OnInitDialog();
CreateThread(nullptr, 0, thread_proc, (LPVOID)m_hWnd, 0, nullptr);
return TRUE;
}
LRESULT on_wm_user1(WPARAM, LPARAM)
{
MessageBox(L"finished");
return 0;
}
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
ON_MESSAGE(WM_USER1, on_wm_user1)
END_MESSAGE_MAP()
我有一个 MFC 应用程序,它尝试使用 cURL 获取页面。当 运行 应用程序时,对话框会暂时无响应。有什么办法可以解决这个问题吗?
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
static std::string GetPage(const char* url)
{
CURL *curl;
CURLcode res;
std::string page;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &page);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
return page;
}
InitInstance():
CWinApp::InitInstance();
CEpicDlg dlg;
m_pMainWnd = &dlg;
dlg.Create(IDD_MAIN);
dlg.ShowWindow(SW_SHOW);
GetPage("http://example.com/page");
dlg.RunModalLoop(MLF_NOIDLEMSG);
如前所述,您必须 运行 单独的工作线程中的函数。
CreateThread
+ WaitForSingleObject
可能表现得像一个阻塞函数,这取决于它是如何实现的...
一种替代方法是 运行 工作线程并在 GUI 线程中继续。工作线程完成后,使用同步对象让 GUI 线程了解状态。或者使用 PostMessage
通知 GUI 线程工作线程完成。确保 url 字符串数据不会在没有同步的情况下同时在两个线程之间共享...
注意,使用CDialog::DoModal
并初始化OnInitDialog
中的数据。您可能还想覆盖 OnCancel
以在退出 window.
#define WM_USER1 (WM_USER + 1)
DWORD WINAPI thread_proc(LPVOID ptr)
{
//simulate a blocking function (don't put Sleep in final code)
Sleep(2000);
HWND hwnd = (HWND)ptr;
if(IsWindow(hwnd)) PostMessage(hwnd, WM_USER1, 0, 0);
return 0;
}
class CMyDialog : public CDialog
{
public:
CMyDialog(int id, CWnd* wnd) : CDialog(id, wnd) {}
BOOL OnInitDialog()
{
CDialog::OnInitDialog();
CreateThread(nullptr, 0, thread_proc, (LPVOID)m_hWnd, 0, nullptr);
return TRUE;
}
LRESULT on_wm_user1(WPARAM, LPARAM)
{
MessageBox(L"finished");
return 0;
}
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
ON_MESSAGE(WM_USER1, on_wm_user1)
END_MESSAGE_MAP()