2011-12-28 34 views
2

私はタイマを使用して非同期関数を実装したC++ライブラリ(Win32コンソール)を持っています。非同期メソッドは、デバイス情報を返します。Windowsメッセージループを使用したコールバック実装

別のスレッド「タイマースレッド」を作成して非表示のウィンドウを作成した後、SetTimer()を呼び出して、実装されたメッセージループを呼び出します。

タイマーが期限切れになると、コールバックが有効になります。

コンソールアプリケーションでライブラリを使用するとうまくいきます。

MFCアプリケーションでは、コールバックがトリガされたときにユーザーインターフェイスを更新するためのポストメッセージを出しています。投稿メッセージが機能していません。

ライブラリ内のメッセージループを削除すると、MFCアプリケーションで問題なく動作しています。

私はという結論に来た:私は、問題が原因2つのメッセージにあると思い

は、1 MFC(メインスレッド)とTimerThreadメッセージループをループします。したがって、コールバックが呼び出され、その後のPostMessageはTimerThreadメッセージループを引き起こし、MFC(メインスレッド)メッセージループでは報告されません。

TimerThreadメッセージループを削除すると、MFCアプリケーションで問題なく動作しますが、コンソールアプリケーションでは機能しません。

どのようにこの問題を解決できますか?私は、コールバックを得るためにIDeviceEnumerationCallbackを実装していますMFC /コンソールアプリケーションで

class IDeviceEnumerationCallback 
{ 
    public: 
     virtual void onDeviceDiscovered(DeviceInfo* pDeviceInfo,unsigned short nNoOfDevice) = 0; 
}; 

class IDeviceDiscovery 
{ 
    public: 
     virtual int InitialiseDiscovery(IDeviceEnumerationCallback*) = 0; 

     virtual void UnInitialiseDiscovery() = 0; 

     virtual int EnumerateDevice() = 0; 
}; 

class CDeviceDiscovery:IDeviceDiscovery 
{ 
    //Implementation 
} 

私はBonjour APIを使用してデバイスを列挙しています。Bonjour APIのすべてのメソッドはコールバックです。

Bonjour APIを使用してデバイスを列挙してから400   ms後に結果を返すよう呼びかけています。コールバックが呼び出されたときのMFCアプリケーションでは、ユーザーインターフェイスを更新するためにPostMessage()を実行しています。

私はWindowsメッセージポンプなしで試しました。私はSetTimer関数を持っていましたが、MFCアプリケーションでは動作していますが、コンソールアプリケーションではコールバックが呼び出されないため、ここでメッセージポンプを実装しました。今はMFCアプリケーションのために働いていません。

+0

あるスレッドから別のスレッド/メッセージループによって管理されているウィンドウにメッセージを投稿するのは問題ありません。ハンドルが正しいと仮定して、WindowProcはOKというメッセージで呼び出されます。 PostMessage()は何を返しますか? –

+0

'SetTimer'は悪名高くねじれていて、エラーを起こしやすいことが知られています。メッセージは投稿されませんが、 'GetMessage'を呼び出したときにのみ作成されますが、キューに優先度の高いメッセージがすでに存在する場合は作成されません(冗談なし)。待機可能なタイマーを使用してください。 – Damon

答えて

0

まず、あなたがした何をする理由はありません:、ウィンドウのタイマーを設定するメッセージループを実行し、WM_TIMERメッセージに応答し、コールバックを呼び出し、それにウィンドウを作成、別のスレッドを作成します。

"自分の"スレッドを作成する場合は、実際にこのすべてを必要としません。 Sleep(またはアボートオプションが必要な場合はWaitForXXXX)の単純なループを実装し、コールバックを呼び出すことができます。

通常、タイマーを使用して非表示のウィンドウを作成し、にすると、スレッドを追加しないようにします。つまり、GUIを操作するスレッド(したがって、メッセージループを実行するスレッド)内で、ウィンドウを作成し、メッセージループによって処理されます。実際には、これはあなたのMFCアプリケーションで行うことができますか?

しかし、あなたが言ったように、MFCとコンソールアプリケーションの両方に汎用コードが必要です。

MFCアプリケーションでは、私は コールバックtriggers.theポストメッセージがwokringされていない場合にUIを更新するために、ポストメッセージをしています。

「ジング・ポスト・メッセージ」とは、具体的にはどういう意味ですか?メッセージは、特定のウィンドウまたはスレッドに投稿する必要があります。最初のケースではウィンドウプロシージャにディスパッチされ、2番目のケースではメッセージループの実装がメッセージを処理します。

メッセージを特定のウィンドウに投稿すると、そのハンドル(HWND)はどうやって手に入りますか?あなたのアプリのメインウィンドウ(AfxGetMainWnd)ですか? MFCがメインウィンドウを作成した後、または以前にスレッドが動作を開始するのは何ですか?

あなたは初心者のようです(犯行はありません)、それらは典型的な間違いですので、これらの質問はすべてお願いします。

+0

質問を更新しました –

0

問題は、隠しウィンドウを作成して、代わりにSetTimerを使用するのではなく、バックグラウンド作業にMFCワーカースレッド機能を使用する必要があるということです。

//You create a thread like so. 
// you need a CMyObject only if you need to pass any information 
//to the thread function. 
CMyObject *pNewObject = new CMyObject; 
AfxBeginThread(MyThreadProc, pNewObject); 


//This function will be run in separate thread 
UINT MyThreadProc(LPVOID pParam) 
{ 
    //The parameter that was passed to this function 
    CMyObject* pObject = (CMyObject*)pParam; 

    while(1) 
    { 
     //add your code to do stuff. 

     Sleep(5000); //or whatever your SetTimer interval was 
    } 

    return 0; // thread completed successfully 
} 
+0

MFCアプリケーションは、ライブラリのテストに使用されるseparteアプリケーションです。コールバック関数を使用してライブラリを実装する方法を教えてください。 –

+0

MFCで「隠された」ウィンドウを作成する際に問題はありません。 – valdo

+0

@valdo OPのコード私は彼が2つのメッセージポンプを稼動させたまま問題を抱えていると推測しています。 –

関連する問題