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).aspx以避免需要使用 ThreadPoolTimer。

于 2012-07-19T22:11:14.237 回答