سؤال

I am trying to write a function which, given a number of seconds and a callback, runs the callback after the given number of seconds. The callback does not have to be on the same thread. The target language is C++/CX.

I tried using Windows::System::Threading::ThreadPoolTimer, but the result is a memory access exception. The issue appears to be that the callback implementation (in native C++) can't be accessed from the managed thread that the timer is running its callback on.

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'
}

I don't want to create a thread and sleep on it, because there may be many concurrent delays.

هل كانت مفيدة؟

المحلول

The TimerDoneCallback instance is not kept alive - delegates in C++/CX take weak references to the target object (to avoid circular references). You can override this behavior by using the extended overload of the delegate constructor:

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

The final bool parameter should be true for strong references, and false for weak references. (False is the default.)

You could also consider using the timer class in PPL agents to make a delayed callback: http://msdn.microsoft.com/en-us/library/hh873170(v=vs.110).aspx to avoid needing to use ThreadPoolTimer.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top