如何终止一个 std::thread?

6

我正在开发一个程序,需要从套接字服务器下载一些图片,这个下载工作需要很长时间才能完成。因此,我创建了一个新的std::thread来完成任务。

当下载完成后,std::thread将调用当前类的成员函数,但是该类可能已经被释放了。因此,我遇到了一个异常。

如何解决这个问题?

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
}

欢迎来到Stack Overflow!我已经尽力编辑了您的问题,但请添加代码说明和描述,以便更多了解该主题的人能够看到它。如果需要识别特定问题,请编辑具体的错误信息。祝你好运! - Enamul Hassan
2
为什么不使用std::future<Image> - Superlokkus
1
可能是 C++0x 线程中断 的重复问题。 - kfsone
1
通常情况下,自己使用线程总是一个不好的主意。 - o11c
1个回答

6

不要分离线程。相反,您可以拥有一个数据成员来保存指向thread的指针,并在析构函数中join线程。

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

更新

正如 @milleniumbug 所指出的,由于 thread 对象是可移动的,因此您不需要进行动态分配。所以另一种解决方案如下。

class YourClass {
public:
    ~YourClass() {
        if (_thread.joinable())
            _thread.join();
    }
    void mainProcess() {
        _thread = std::thread(&YourClass::downloadImg, this);
    }
private:
    std::thread _thread;
};

谢谢,我已经尝试过这种方法了,但这是一个特殊情况,“YourClass”是一个游戏场景,用户可以随时弹出此场景,如果这样做,当用户弹出此场景时会阻塞很长时间。 - tobin
在这种情况下,您需要在主线程和下载线程之间进行一些同步。例如,您可以设置一个“停止”标志。下载线程每隔1秒钟检查一次该标志,如果已设置该标志,则退出下载。在析构函数中,首先设置“停止”标志,然后加入线程。 - for_stack
1
如果库被正确设计,它应该有一个停止下载的接口。因此,你可以在析构函数中调用terminate_download接口,而不是设置“停止”标志。如果没有这样的接口,你几乎无能为力。强制终止线程总是一个坏主意。 - for_stack
1
实际上,我渴望知道如何在这个问题中强制终止一个 std 线程。似乎标准库没有提供这样的函数,对吗? - tobin
强制终止线程几乎总是一个坏主意。如果线程被终止,它可能持有资源(锁、互斥量),这些资源将永远不会被释放。 - el.pescado - нет войне
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接