How to terminate a std::thread?
Asked Answered
F

1

6

I am currently developing a program that needs to download some images from the socket server,and the downloading work will execute a long time. So, I create a new std::thread to do that.

Once it's downloaded,the std::thread will call a member function of current Class, but this Class is likely to have been released. So, I got a exception.

How to solve this problem?

void xxx::fun1()
{
   ...
}
void xxx::downloadImg()
{
 ...a long time
  if(downloadComplete)
  {
   this->fun1();
  }
}
void xxx::mainProcees()
{
  std::thread* th = new thread(mem_fn(&xxx::downloadImg),this);
  th->detach();
  //if I use th->join(),the UI will be obstructed
}
Fayfayal answered 23/7, 2016 at 5:19 Comment(4)
Welcome to Stack Overflow! I edited your question as far as I could guess your problem. However, add explanation of code and description so that more people with knowledge of the subject will see it. Please edit in the specific error-message you're encountering in case that's necessary to identify the specific problem. Good Luck!Alfano
Why don't you use a std::future<Image>?Travers
Possible duplicate of C++0x thread interruptionEnteric
Generally, using threads yourself is always a bad idea.Sebaceous
B
6

Don't detach the thread. Instead, you can have a data member that hold a pointer to the thread, and join the thread in destructor.

class YourClass {
public:
    ~YourClass() {
        if (_thread != nullptr) {
            _thread->join();
            delete _thread;
        }
    }
    void mainProcees() {
        _thread = new thread(&YourClass::downloadImg,this);
    }
private:
    thread *_thread = nullptr;
};

UPDATE

Just as @milleniumbug pointed out, you don't need dynamic allocation for the thread object, since it is movable. So the other solution is as follows.

class YourClass {
public:
    ~YourClass() {
        if (_thread.joinable())
            _thread.join();
    }
    void mainProcess() {
        _thread = std::thread(&YourClass::downloadImg, this);
    }
private:
    std::thread _thread;
};
Brightness answered 23/7, 2016 at 5:31 Comment(7)
Thanks,I've tried this method,but it's a special occasion,the "YourClass" is a game scene, users can pop this scene at anytime,if you do ,it will obstruct a long time when users pop this sceneFayfayal
In this case, you have to do some synchronization between the main thread and your download thread. For example, you can have a 'stop' flag. The download thread check the flag every 1 second, if the flag has been set, then exit downloading. In the destructor, set the 'stop' flag first , then join the thread.Brightness
thanks for your help,It works now.If the "downloadImg" function is a interface of a static lirbrary,what should I do?Fayfayal
If the library is designed properly, it should have an interface to stop downloading. So instead of setting the 'stop' flag, you can call this terminate_download interface in your destructor. If it doesn't have such an interface, there is little you can do. It's always a bad idea to terminate a thread forcefully.Brightness
In fact,I'm dying to know how to terminate a std thread forcefully in this problem.. ,seemingly,the standard library not provide a function like this,is't it?Fayfayal
Forcefully terminating a thread is (almost) always bad idea. That thread may hold resources (locks, mutexes) that will be never released if thread is terminated.Broadloom
@el.pescado what if a thread is infact holding a lock and you need to undo that action by killing thread and leaving the "critical" lock - how would that be possible? any idea?Spontaneity

© 2022 - 2024 — McMap. All rights reserved.