C++中的多线程 - 显示动画直到另一个线程完成

发布于 2025-01-27 12:51:30 字数 941 浏览 2 评论 0原文

序言:这是我第一次尝试使用具有多线程的任何语言编写程序。我没有先前在STD ::线程的经验,也没有描述多线程的程序。请让我知道您是否需要更多信息来回答此问题,或者我是否可以重新介绍任何内容以使我的问题更清晰。

假设我有一个简单的动画函数Animate,该功能(目前)无限期地运行;另一个函数任务,代表某些任意执行的代码。

#include <string>

// a simple rotating stick animation: | -> / -> - -> \

void animate()
{
  std::string syms = "|/-\\";
  while (true)
  {
    for (unsigned int ii = 0; ii < syms.length(); ++ii)
    {
      std::cout << syms[ii];
      std::cout << std::string(1, '\b');
    }
  }
}

// arbitrary function

void task()
{
  // code to do something else goes here
}

int main (int argc, char* argv[])
{
  // execute task and animate at the same time;
  // return from animate once task has completed
  return 0;
}

我如何使用std :: thread(或其他一些标题/库)允许taskAnimate互相通信,以便任务在“背景”和Animate运行直到任务已经完成?

Preface: this is my first attempt at writing a program in any language with multi-threading. I have no prior experience with std::thread, or with describing multi-threaded programs at all. Please let me know if you need more information to answer this question, or if I can reword anything to make my question clearer.

Suppose I have a simple animation function animate, which (for now) runs indefinitely; and another function task, which represents some arbitrary code to execute.

#include <string>

// a simple rotating stick animation: | -> / -> - -> \

void animate()
{
  std::string syms = "|/-\\";
  while (true)
  {
    for (unsigned int ii = 0; ii < syms.length(); ++ii)
    {
      std::cout << syms[ii];
      std::cout << std::string(1, '\b');
    }
  }
}

// arbitrary function

void task()
{
  // code to do something else goes here
}

int main (int argc, char* argv[])
{
  // execute task and animate at the same time;
  // return from animate once task has completed
  return 0;
}

How can I use std::thread (or some other header/library) to allow task and animate to communicate with each other, such that task runs in the "background" and animate runs until task has completed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

你的呼吸 2025-02-03 12:51:30

我已经使用了您的示例代码,并试图用std :: thread从您的意图中填充空白。我添加了一些内联评论来解释正在发生的事情。如果不清楚的话,或者我弄错了,请随时在评论中询问。

我想强调,虽然这个示例 使用std :: thread在玩具示例中创建并连接一个单独的线程。
它不会以正确的方式在线程之间同步共享数据。
MT环境中的共享数据是事物变得毛茸茸的,最糟糕的是,它可以创建一些最难调试错误的地方。这就是为什么书籍和工作示例对于任何实质性多线程程序都很重要的原因。

#include <string>
#include <thread>
#include <chrono>
#include <iostream>

// a simple rotating stick animation: | -> / -> - -> \

//
void animate(bool * should_animate)
{
  // Using this namespace lets us use the "100ms" time literal in the sleep_for() function argument.
  using namespace std::chrono_literals;

  std::string syms = "|/-\\";
  while (*should_animate)
  {
    for (unsigned int ii = 0; ii < syms.length(); ++ii)
    {
      std::cout << syms[ii];
      std::cout << std::string(1, '\b');

      // I had to flush cout so that the animation would show up
      std::cout.flush();
      // I added some delay here so that the animation is more visible
      std::this_thread::sleep_for(100ms);
    }
  }
}

// arbitrary function

void task()
{
  using namespace std::chrono_literals;
  // I have this thread waiting for 2 seconds to simulate a lot of work being done
  std::this_thread::sleep_for(2s);
}

int main (int argc, char* argv[])
{

  // This line creates a thread from the animate() function
  // The std::thread constructor is flexible, in that it can take a function with any number and type of arguments and
  // make a thread out of it
  // Once the thread is created, it gets sent to the operating system for scheduling right away in a separate thread
  // I'm passing in a pointer to `should_animate` to use that value as a basic way to communicate to the animate thread to signal when it should stop running.
  // I'm doing this to keep the example simple, but I stress that this isn't a good idea for larger scale programs
  // Better to use propper signals or event queues
  bool should_animate = true;
  std::thread thread_animate(animate, &should_animate);

  // This line creates a thread for the worker task
  // That separate thread can be referenced by tis std::thread object
  // Once the functions finish running, the thread associated with it is "joined"
  std::thread thread_task(task);

  // 'join' pauses the main thread to wait for the associated thread to finish running in the background.
  thread_task.join();

  // By this point in the program, the `task()` function has finished running, so we can flag
  // the animate task to finish running so its thread can be joined
  should_animate = false;
  // Wait for the animate thread to get the message and finish
  thread_animate.join();


  std::cout << "Done!" << std::endl;
  return 0;
}

如果您想进一步,我建议您推荐一些链接。

I've taken your example code and tried to fill in the blanks from your intention with std::thread. I've added some comments inline to explain what's going on. If something's not clear, or I got it wrong, feel free to ask in the comments.

I want to stress though that this example only uses std::thread to create and join a separate thread in a toy example.
It does not synchronize shared data between threads in a correct way.
Shared data in MT environments is where things get hairy and the worst thing is that it can create some of the hardest to debug bugs out there. That's why the books and working examples are important for any substantial multithreaded program.

#include <string>
#include <thread>
#include <chrono>
#include <iostream>

// a simple rotating stick animation: | -> / -> - -> \

//
void animate(bool * should_animate)
{
  // Using this namespace lets us use the "100ms" time literal in the sleep_for() function argument.
  using namespace std::chrono_literals;

  std::string syms = "|/-\\";
  while (*should_animate)
  {
    for (unsigned int ii = 0; ii < syms.length(); ++ii)
    {
      std::cout << syms[ii];
      std::cout << std::string(1, '\b');

      // I had to flush cout so that the animation would show up
      std::cout.flush();
      // I added some delay here so that the animation is more visible
      std::this_thread::sleep_for(100ms);
    }
  }
}

// arbitrary function

void task()
{
  using namespace std::chrono_literals;
  // I have this thread waiting for 2 seconds to simulate a lot of work being done
  std::this_thread::sleep_for(2s);
}

int main (int argc, char* argv[])
{

  // This line creates a thread from the animate() function
  // The std::thread constructor is flexible, in that it can take a function with any number and type of arguments and
  // make a thread out of it
  // Once the thread is created, it gets sent to the operating system for scheduling right away in a separate thread
  // I'm passing in a pointer to `should_animate` to use that value as a basic way to communicate to the animate thread to signal when it should stop running.
  // I'm doing this to keep the example simple, but I stress that this isn't a good idea for larger scale programs
  // Better to use propper signals or event queues
  bool should_animate = true;
  std::thread thread_animate(animate, &should_animate);

  // This line creates a thread for the worker task
  // That separate thread can be referenced by tis std::thread object
  // Once the functions finish running, the thread associated with it is "joined"
  std::thread thread_task(task);

  // 'join' pauses the main thread to wait for the associated thread to finish running in the background.
  thread_task.join();

  // By this point in the program, the `task()` function has finished running, so we can flag
  // the animate task to finish running so its thread can be joined
  should_animate = false;
  // Wait for the animate thread to get the message and finish
  thread_animate.join();


  std::cout << "Done!" << std::endl;
  return 0;
}

If you want to take it a little further, here's some links I'd recommend.

  • This was the best tutorial I could find in the first page of google (most results seemed bad). Seems like a good jumping off point https://solarianprogrammer.com/2011/12/16/cpp-11-thread-tutorial/
  • cppreference is the best C++ reference site I know of, and I usually have at least one tab on it all day. Because it is reference, its difficult to dig straight into it. Each section header of this page covers one multithreaded topics. "Threads" and "Mutual Exclusion" are the most common things uses in MT. https://en.cppreference.com/w/cpp/thread
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文