【问题标题】:Check if a thread is finished to send another param to it检查线程是否完成以向其发送另一个参数
【发布时间】:2018-08-06 21:27:21
【问题描述】:

我想检查线程作业是否已完成以再次调用它并向其发送另一个参数。代码是这样的:

void SendMassage(double Speed)
{
    Sleep(200);
    cout << "Speed:" << Speed << endl;

}

int main() {

    int Speed_1 = 0;
    thread f(SendMassage, Speed_1);

    for (int i = 0; i < 50; i++)
    {
        Sleep(20);

        if (?)
        {
            another call of thread // If last thread done then call it again, otherwise not.
        }

        Speed_1++;
    }

}

我该怎么做?

【问题讨论】:

  • 您可以验证线程尚未完成,但这不会告诉您下一刻(当您实际尝试向其发送某些内容时)它的状态。

标签: c++ multithreading


【解决方案1】:

使用,例如,原子标志来指示线程已完成:

std::atomic<bool> finished_flag{false};

void SendMassage(double Speed) {
   Sleep(200);
   cout << "Speed:" << Speed << endl;
   finished_flag = true;    
}

int main() {    
   int Speed_1 = 0;
   thread f(SendMassage, Speed_1);

   while (Speed_1 < 50) {
      Sleep(20);    
      if (finished_flag) {
         f.join();
         finished_flag = false;             
         f = std::thread(SendMassage, Speed_1);
      }          
      Speed_1++;    
   }
   f.join();
}

工作示例:https://wandbox.org/permlink/BrEMHFvlInshBy5V


请注意,根据您的代码,我假设您不想在检查线程 f 是否已完成时阻塞。否则,只需致电f.join()

【讨论】:

  • 谢谢丹尼尔,您的回答帮助我定义了finished_flag,以便在我的线程之间使用它。但我不明白你为什么在 if 循环中调用 f.joine() ?还有最后一行代码?
  • @Rasoul 因为您必须在封装底层执行线程std::thread 对象上调用f.join()f.detach()。这就是 C++ 中线程的设计方式。
  • 但是请注意,这实际上并不能回答所提出的问题。此代码等待线程终止,然后启动新线程。问题是关于重用同一线程。我不知道这种区别是否重要。因为答案被接受了,可能不会。
  • @PeteBecker 是的,从 OP 是否要重用 执行线程std::thread 对象的问题中不清楚。我的代码是后者。
  • @Rasoul -- “等于重用” -- 是和否。如果您重用现有线程,则不会重新初始化线程本地对象——它们会保留其旧值。如果这很重要,那可能是个问题。除此之外,重用线程而不是启动新线程主要是为了性能。重用已经存在的线程更快。这就是使用线程池背后的逻辑。
【解决方案2】:

如果你想等到一个线程完成它的工作而不使用睡眠,你需要调用它的 join 方法,像这样

thread t(SendMassage, Speed_1);
t.join();
//Code here will start executing after returning from join

您可以在此处阅读更多信息http://en.cppreference.com/w/cpp/thread/thread/join

关于发送另一个参数,我认为最好的方法是将它拆分为另一个函数,在这个线程加入后调用,如果你需要一些只有在函数内部知道的信息,你可以创建一个类它将将该信息存储在其字段中,并在您正在线程化的函数中使用它。

【讨论】:

    【解决方案3】:

    这样做可能最简单的方法就是joining 线程。没什么聪明的,但是...

    好的,但是如果你的主线程一直处于休眠状态,那么你为什么还要有另一个线程呢,所以你肯定在寻找更聪明的东西。

    我个人喜欢排队的原则;你可以使用 e。 G。 std::deque 用于:

    您的生产者线程放入一些值,您的消费者线程只是将它们取出。当然,您需要通过std::mutex(或通过其他适当的方式)保护您的队列免受竞争条件的影响...

    如果条目可用,消费者将在无限循环中运行,处理队列,如果不是这种情况,则休眠。看看这个response 了解如何等待......

    但是,存在队列已满的危险,因此,如果您发现生产者速度太快,您可能会在停止或至少减慢生成新值时定义一些阈值。但是,队列还有另一个优点:如果您的生产者太快,您可能有多个消费者,它们都服务于同一个队列(根据您的需要,将结果放在一起可能需要一些额外的努力来保持正确的排序)。

    承认,这是一项相当多的工作,可能值得付出努力,也可能是矫枉过正。如果更简单的方法已经满足您的需求,Daniel's 的答案也很好......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-23
      • 1970-01-01
      • 1970-01-01
      • 2011-02-15
      • 2014-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多