简体   繁体   English

带有 std::cout 的多线程控制台文本动画

[英]Multi-thread console text animations with std::cout

I'm trying to create a function that can animate multiple strings to the console at the same time.我正在尝试创建一个可以同时将多个字符串动画到控制台的函数。 By "animate," I mean print a character, wait a specified amount of time, then print the next character, and so on. “动画”是指打印一个字符,等待指定的时间,然后打印下一个字符,依此类推。

This is what I've tried so far:这是我迄今为止尝试过的:

/**
 @param msg        Message to animate
 @param sleep_time Time to wait between each letter
 @param wait       Whether or not to wait for the current thread to join before returning
*/
void animate(const std::string& msg, const unsigned long long sleep_time, const bool wait = true)
{
    const std::atomic<std::chrono::milliseconds> t_sleep_time =
        std::chrono::milliseconds(sleep_time);

    std::stringstream msg_strm;
    msg_strm << msg;

    std::thread animate_thread([&msg_strm, &t_sleep_time]() -> void
    {
        char letter;

        while ((letter = msg_strm.get()) != EOF)
        {
            std::cout << letter << std::flush;
            std::this_thread::sleep_for(t_sleep_time.load());
        }

        return;
    });

    if (wait)
    {
        animate_thread.join();
    }
    else
    {
        animate_thread.detach();
    }
}

This is the driver code for it:这是它的驱动程序代码:

int main()
{
    animate("Hello", 500, false);
    std::cout << '\n' << std::endl;
    animate("Welcome", 400, true);
    std::cout << "\n\nEnd" << std::endl;
}

And this is the output ("Wecome" animates as sluggishly):这是输出(“Wecome”动画缓慢):


Welcome

End

What happened to "Hello"? “你好”怎么了? I'm very new to multi-threading, so a detailed explanation would be very much appreciated.我对多线程很陌生,因此非常感谢详细的解释。 Ideally, what I'd like to happen, is to have "Hello" animating on one line and "Welcome" on the next.理想情况下,我希望发生的事情是在一行上播放“你好”动画,在下一行播放“欢迎”。 Is this possible?这可能吗?

First of all msg_strm lives on the stack thus you cannot pass it by value to the thread because it goes out of scope and that is why, most probable Hello was not showing.首先, msg_strm存在于堆栈中,因此您无法将其按值传递给线程,因为它超出了范围,这就是为什么最有可能的Hello没有显示的原因。 Also another problem that you have is that you are calling detach thus the program might exit before the first thread finish.您还有另一个问题是您正在调用detach因此程序可能会在第一个线程完成之前退出。

To achieve what you are trying to do I suggest to use ANSI escape codes .为了实现您的目标,我建议使用ANSI escape codes Therefore the following might not work on all command prompts.因此,以下内容可能不适用于所有命令提示符。 Also note that std::cout is not thread safe if you print in steps.另请注意,如果您分步打印,则std::cout不是线程安全的。

#include <atomic>
#include <iostream>
#include <string>
#include <thread>

std::atomic<int> g_lines = 1;

std::thread animate(const std::string& msg, const unsigned long long sleep_time)
{
    // NOTE: `[=]` means capture all variables used by value. Note that globals
    // are not captured.  Also note that capture by value is needed because
    // `msg` can go out-of-scope.
    return std::thread([=] {
        auto line = g_lines++;

        for (size_t column = 1; column <= msg.size(); column++)
        {
            // using `ANSI escape codes` move the cursor to the correct
            // position; \x1B[{line};{column}H

            std::cout << "\x1B[" + std::to_string(line) + ";"
                             + std::to_string(column) + "H" + msg[column - 1];

            std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time));
        }
    });
}

int main()
{
    auto t1 = animate("Hello", 500);
    auto t2 = animate("Welcome", 400);

    // you need to join all threads else if you call detach, the program might
    // exit before all threads finish.
    t1.join();
    t2.join();

    std::cout << "\n\nEnd" << std::endl;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM