5

秒数とコールバックを指定すると、指定された秒数の後にコールバックを実行する関数を作成しようとしています。コールバックは同じスレッド上にある必要はありません。対象言語は C++/CX です。

Windows::System::Threading::ThreadPoolTimer を使用してみましたが、結果はメモリ アクセス例外です。問題は、コールバックの実装 (ネイティブ C++) が、タイマーがそのコールバックを実行しているマネージド スレッドからアクセスできないことです。

ref class TimerDoneCallback {
private:
    function<void(void)> m_callback;
public:
    void EventCallback(ThreadPoolTimer^ timer) {
        m_callback(); // <-- memory exception here
    }
    TimerDoneCallback(function<void(void)> callback) : m_callback(callback) {}
};
void RealTimeDelayCall(const TimeSpan& duration, function<void(void)> callback) {
    auto t = ref new TimerDoneCallback(callback);
    auto e = ref new TimerElapsedHandler(t, &TimerDoneCallback::EventCallback);
    ThreadPoolTimer::CreateTimer(e, duration);
}
void Test() {
    RealTimeDelayCall(duration, [](){}); //after a delay, run 'do nothing'
}

多くの同時遅延が発生する可能性があるため、スレッドを作成してその上でスリープしたくありません。

4

1 に答える 1

3

TimerDoneCallbackインスタンスは存続しません-C++/ CXのデリゲートは、ターゲットオブジェクトへの弱参照を取ります(循環参照を回避するため)。デリゲートコンストラクターの拡張オーバーロードを使用して、この動作をオーバーライドできます。

auto e = ref new TimerElapsedHandler(t, &TimerDoneCallback::EventCallback, CallbackContext::Any, true);

最後のboolパラメーターは、強参照の場合はtrue、弱参照の場合はfalseである必要があります。(デフォルトはFalseです。)

また、PPLエージェントのタイマークラスを使用して遅延コールバックを作成することも検討できます:http://msdn.microsoft.com/en-us/library/hh873170 (v = vs.110) .aspxThreadPoolTimerを使用する必要がないようにします。

于 2012-07-19T22:11:14.237 に答える