2017-04-26 20 views
0

私はC++を初めてお使いで、インターネットから情報を取得する必要があるアプリケーションを設計しています。インターネットに接続できない場合や、アプリケーションは数秒間フリーズします。私のアプリケーションにはキーボードへのフックも付いているので、アプリケーションがフリーズするとWindowsも動きます。新しいスレッドでhttpリクエストを送信するC++

私のアプリケーションはWindowsのみです。

これは私の問題のシミュレーションです:

std::string instruction; 
std::string otherValue; 
int timerId; 

int main(int argc, char* argv[]) 
{ 
    StartKeysListener(); //Keyboard Hook 

    timerId = SetTimer(nullptr, 0, 5000, static_cast<TIMERPROC>(TimerCallback)); 

    MSG msg; 
    while (GetMessageA(&msg, nullptr, 0, 0) > 0) { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
} 

VOID CALLBACK TimerCallback(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime) 
{ 
    DownloadInstructions(); 
} 

std::string DownloadInstructions(std::string url) 
{ 
    std::string response = HttpRequest(url); //HttpRequest is a function that uses Windows SOCKET to send an http request 

    if (!response.empty()) 
    { 
     instruction = response.substr(0, 5); 
     otherValue = response.substr(6, 15); 
    } 
} 

私はstd::asyncを使用して、新しいスレッド上で「DownloadInstructions」関数を呼び出す試してみましたが、私は更新するコールバックにサーバの応答を返す方法がわかりません"命令"および"otherValue"変数。

どうすればこの問題を解決できますか? Googleで探しているものが見つかりませんでした。

+0

UIウィンドウにカスタムウィンドウメッセージを投稿します。ウィンドウメッセージはWPARAMとLPARAMにデータを置くことも、LPARAMのポインタを渡すこともできます。データが入っている構造体に渡します。たとえばhttp://stackoverflow.com/questions/19144112/how-can-worker-threads-communicate -with-main-ui-thread –

+0

あなたのサービスがRESTfulなら、Casablancaを使うことができます。独自の非同期I/Oをローリングすることは難しいでしょう。 https://casablanca.codeplex.com/wikipage?タイトル=のHttp%20Client%20Tutorial –

答えて

2

Win32スタイルのメッセージループを使用している場合、情報をワーカースレッドからメインスレッドに戻す通常の方法は、メッセージを送信することです。 (あなたのサンプルコードは、少なくともダミーのHWNDのダミーを必要としているように書かれているようには見えません。)WM_APPからのオフセットとしてカスタムメッセージ(定義済みのシステムメッセージではありません)を定義することができます。その後DownloadInstructionsであなたはダウンロードがHWNDパラメータがからのスレッドに渡される(非同期メッセージを送信します)PostMessage APIを使用して、完了したことをメインスレッドに通知することができ

#define WM_INSTRUCTIONS_LOADING (WM_APP + 0) 
#define WM_INSTRUCTIONS_READY (WM_APP + 1) 
/* ... */ 

:あなたのような何かを行うことができますメインループ:

PostMessage(WM_INSTRUCTIONS_READY, hwndMain, 0, 0); 

DownloadInstructionsは実際に別のスレッドで実行されているようには見えません。 SetTimer APIを使用しています.というメッセージがイベントループに送信されます。メッセージはイベントループで処理され、メインスレッドで処理されます。

本当に非同期にするには、別のスレッドを作成する必要があります。 std::asyncを使用するメカニズムは、CreateThreadとはかなり異なります。 std::asyncコールはスレッドを生成し、結果を得るために参加する必要があるstd::futureを返します。これは現在のデザインにはあまり適していません。別のスレッドとしてDownloadInstructionsをスポーンして、void*引数ポインタを介していくつかのコンテキスト(少なくともHWNDにポストバック)を渡すだけで十分です。

これまで述べてきたように、かなり古き良き低レベルのC Win32 APIを使用してC++アプリケーションを作成してもよろしいですか?これらのすべての種類の作業をより簡単に行うためにはるかに高いレベルのAPIを提供するC++のライブラリとフレームワークは数多くあります。

+0

_Userメッセージ(事前に定義されたシステムメッセージとは対照的に)WM_USER_からのオフセットとして定義することができる - [ 'WM_APP']でなければならない(https://msdn.microsoft.com/en-us /library/windows/desktop/ms644930(v=vs.85).aspx)定義済みのコントロールでWM_USER範囲のメッセージを使用する可能性があるためです。 – zett42

+0

Trueですが、既存のウィンドウをサブクラス化する場合にのみ問題になります。あなたが登録するウィンドウクラスについては、重複はありません。とにかく、それに応じて投稿を変更しました。 (関連http://stackoverflow.com/questions/30843497/wm-user-vs-wm-app) – gavinb

関連する問題