26

根据This Question,我正在使用线程来终止用户输入的函数。我的代码看起来像:

bool stopper = false;
thread stopThread(userStop, &stopper);      // start thread looking for user input
for(int i = 0; i < 1000; i++) {
    if(stopper) { break; }                  // break if desired
    // Do stuff
}
return 0;

在哪里,

userStop(bool *st) {
    char chChar = getchar();
    if(chChar == '\n') {
        *st = true;
    }
}

当我运行它时,我得到了错误terminate called without an active exception。基于这些问题:线程终止调用没有活动异常C++终止调用没有活动异常;看起来像是因为我不再“加入”线程了。

问题是,我不想“加入”线程——因为这样用户将需要为终止提供输入userStop(),但我只希望用户在 for 循环被破坏时提供输入(其中不一定)。

谢谢!

4

3 回答 3

39

您遇到的问题是stopThread堆栈超出范围的结果。C++ 标准对此有以下说法:

30.3.1.3 线程析构函数[thread.thread.destr]

〜线程();

如果joinable()则终止(),否则无效。[注意:在其析构函数中隐式分离或加入joinable()线程可能导致难以调试正确性(分离)或性能(加入)错误,仅在引发异常时遇到。因此,程序员必须确保在线程仍可连接时永远不会执行析构函数。——尾注]

这意味着你不应该让线程在没有先调用join()or的情况下超出范围detach()

您描述它的方式,您希望线程在不加入的情况下超出范围,因此它将在您的应用程序运行时继续运行。这需要调用detach(). 从那里,我只能提供一点智慧......

  • 该线程现在完全负责自己的生命周期。如果它没有自行返回,它将永远运行(直到进程终止)。

  • 您正在获取用户输入,可能来自类似cinor之类的东西getch()。如果这些是从多个线程访问的,则您无法确保它们的库实现中没有竞争条件。轻装上阵。

于 2012-12-22T06:45:31.173 回答
4

在您的标准输入线程中,您需要从输入中异步读取。并在停止阅读的需求和新的输入时醒来。

终止线程而不加入是不合理的事情。所以你需要做的就是说“哟线程,现在完成”,然后能够期望连接会迅速完成。在某些情况下,这甚至可以通过两步握手(“哟线程,完成”,然后是“好的,我设法清理,现在加入我”)。

请注意,您的循环1000看起来非常荒谬:用户输入超时通常应基于实际时间传递,或发生的其他一些使用户输入无用的事件。

于 2012-12-22T02:26:23.960 回答
1

终止一个线程是个坏主意——你应该让你的线程优雅地退出。如果您确实终止了线程,您最终会导致getch()函数中的代码意外结束。如果该代码正在管理数据结构、分配或释放内存或执行其他必须执行直到完成的工作,该怎么办?你最终会使某些东西处于无效状态,并且在执行该无效状态时最终会崩溃。

于 2012-12-22T02:15:47.940 回答