且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

从后台线程错误修改自动布局引擎,从C ++

更新时间:2022-12-09 11:28:35

All access to the UI classes must take place on the main thread. Your boost timer does not run on the main thread.

Thus, it probably makes sense to have your timer fire on the main thread. You can use the standard libdispatch API, even with pure C++ code (does not have to be .mm ObjC++).

Be sure to add #include <dispatch/dispatch.h> to your CPP implementation file.

The following code change will make sure that the timer always runs on the Cocoa main thread.

void TimerImpl::TimerTick(const boost::system::error_code& e) {
    if(e != boost::asio::error::operation_aborted) {
        time_remaining_--;
        std:: cout << "C++: TimerTick() with " << std::to_string(time_remaining_) << " seconds remaining.\n";

        if (time_remaining_ > 0) {
            timer_.expires_from_now(boost::posix_time::seconds(1));
            timer_.async_wait(boost::bind(&TimerImpl::TimerTick, this, boost::asio::placeholders::error));

            auto listener = listener_;
            auto time_remaining = time_remaining_;
            dispatch_async(dispatch_get_main_queue(), ^{
               listener->TimerTicked(time_remaining);
            });
        } else {
            auto listener = listener_;
            dispatch_async(dispatch_get_main_queue(), ^{
                listener->TimerEnded();
            });
        }
    }
}

I assume the rest of that code works. All I did was modify how the callbacks are invoked. Note that we create a copy of the listener_ shared_ptr and the time_remaining_ value. These will be captured (and copied) by the block that gets executed on the main thread.

If you can guarantee that this will not delete before that block executes, then you can implicitly capture this...

dispatch_async(dispatch_get_main_queue(), ^{
   listener_->TimerTicked(time_remaining_);
});

Or, if you enable shared-from-this, you can create a copy of the shared pointer to this and capture it that way...

auto self = shared_from_this();
dispatch_async(dispatch_get_main_queue(), ^{
   self->listener_->TimerTicked(self->time_remaining_);
});

There are a number of ways to do this, but this may be the easiest, and now you ensure all your timers fire through to the Cocoa main thread.

相关阅读

技术问答最新文章