11

Windows nodejs アドオンで、メッセージを受信するためのウィンドウを作成しました。

Handle<Value> MakeMessageWindow(const Arguments &args) { // exposed to JS
    ...
    CreateWindow(L"ClassName", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0);
    ...
}

wndproc 関数があります。

Local<Function> wndProc;
LRESULT APIENTRY WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    // pack up the arguments into Local<Value> argv
    wndProc->Call(Context::GetCurrent()->Global(), 3, argv);
}

次に、メッセージをポンピングする必要があります。通常、次のようなことをします

MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) 
{
     TranslateMessage(&msg);
     DispatchMessage(&msg);
}

...しかし、それは v8 イベント ループをブロックするだけなので、うまくいきません。

v8 をブロックせず、ウィンドウがメッセージを受信したときに JS 関数を呼び出せるように Windows メッセージを送り込むにはどうすればよいですか?

libuv が役割を果たすと思いますが、別のスレッドで実行されている C から JS 関数を安全に呼び出す方法が正確にはわかりません。特に、uv_async_send呼び出すたびにコールバックを呼び出すことが保証されていないため、私の JS コールバックは、ウィンドウ メッセージが受信されるたびに呼び出されます。

4

3 に答える 3

11

私の間違いは、V8 スレッドでウィンドウを作成しようとしたことです。代わりに、新しいスレッドでウィンドウを作成し、独自のメッセージ ポンプ ループを実行uv_thread_createする関数を呼び出すために使用する必要があります。

次に、wndproc 関数は、受信したメッセージをスレッド セーフな方法でキューに保存し、uv_async_sendメッセージが到着したことを V8 スレッドに通知するために使用する必要があります。

uv_async_initメッセージがエンキューされた後、( に渡された) V8 スレッドの関数が呼び出されます。この関数は (スレッドセーフに) 保留中の各メッセージをキューからポップし、JS コールバックを呼び出します。

于 2013-07-19T23:28:34.330 に答える
1

メッセージポンプが必要なCanon の EDSDK でこれを行う必要がありました。

libuvuv_idle_tはこれに適した候補です。

その名前にもかかわらず、アイドル ハンドルは、ループが実際に「アイドル」である場合ではなく、ループの反復ごとに呼び出されるコールバックを取得します。</p>

例:

#include <uv.h>

uv_idle_t* idle = new uv_idle_t();
uv_idle_init(uv_default_loop(), idle);
uv_idle_start(idle, idle_winmsg);

void idle_winmsg (uv_idle_t* idle) {
    MSG msg;
    if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}
于 2019-09-12T07:40:29.870 に答える
0

その本当の理由がわかりました。

Node.js イベント ループは、I/O のポーリングでスタックし、保留中の未処理の I/O 操作がない場合、イベント ループはスリープ状態になります。

idleNode.js イベント ループが実行する I/O ポーリングの前にprepare実行されますが、スケジュールされた作業はなく、せいぜい 1 つまたは 2 つのコールバックが表示される可能性があります。

I/O 完了ポートを通知するために使用できる Win32 メッセージ API がないため、この問題を解決する方法はありません。別のスレッドで Win32 メッセージ ループを実行する必要があります。

于 2018-07-27T08:19:31.507 に答える