Rust中使用thread:sleep和print导致的执行顺序问题

Rust中使用thread:sleep和print!宏引起的执行顺序问题探究

以下是C#代码:

static void Main(string[] args)
{
	System.Console.Write("Hello ");
	System.Threading.Thread.Sleep(System.TimeSpan.FromSeconds(3));
	System.Console.Write("World");
}

在Visual Studio界面按F5编译并执行,在打印出Hello 字符串后,等待3秒(大约),打印出World字符串。

同样的逻辑,以下是Rust代码:

fn main() {
	print!("Hello ");
	std::thread::sleep(std::time::Duration::from_secs(3));
	print!("World");
}

使用cargo run编译并运行,奇怪的一幕出现了,等待了大概3秒之后,屏幕一起打印出了Hello World字符串!

难道,Rust中的thead::sleep()方法打乱了print!的执行顺序?

带着疑问,我查看了print!宏的实现方法:

#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(print_internals)]
macro_rules! print {
    ($($arg:tt)*) => ($crate::io::_print($crate::format_args!($($arg)*)));
}

看太懂(😂😂😂)。。。往上看:

/// Prints to the standard output.
///
/// Equivalent to the [`println!`] macro except that a newline is not printed at
/// the end of the message.
///
/// Note that stdout is frequently line-buffered by default so it may be
/// necessary to use [`io::stdout().flush()`][flush] to ensure the output is emitted
/// immediately.
///
/// Use `print!` only for the primary output of your program. Use
/// [`eprint!`] instead to print error and progress messages.
///
/// [flush]: crate::io::Write::flush
///
/// # Panics
///
/// Panics if writing to `io::stdout()` fails.
///
/// # Examples
///
/// ```
/// use std::io::{self, Write};
///
/// print!("this ");
/// print!("will ");
/// print!("be ");
/// print!("on ");
/// print!("the ");
/// print!("same ");
/// print!("line ");
///
/// io::stdout().flush().unwrap();
///
/// print!("this string has a newline, why not choose println! instead?\n");
///
/// io::stdout().flush().unwrap();
/// ```

哈哈,原来是因为使用print!宏时,stdout有默认的行缓冲,所以导致不能立即把缓冲区内容刷新到屏幕上。如果需要立即显示,需要使用 io::stdout().flush()方法立即刷新。

于是在thread::sleep之前添加flush()方法:

fn main() {
	print!("Hello ");
	std::io::stdout().flush().unwarp();
	std::thread::sleep(std::time::Duration::from_secs(3));
	print!("World");
}

一切正常。

C#中对使用write打印内容时立刷新到了屏幕,而Rust中的print!宏却没有。但是Rust的println!宏实现了立即刷新功能,其中考量,不得而知。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!