即使在 C# 中忙碌时也强制控制台应用程序打印

Rah*_*han 2 .net c# multithreading console-application

我有一个简单的控制台应用程序,如下所示:

private static void Main (string [] args)
{
    System.Console.WriteLine("Initializing context...");
    Database.Context.Initialize();

    System.Console.WriteLine("Creating server...");
    var server = new Server();
    server.OnStarting += Server_OnStarting;
    server.OnStarted += Server_OnStarted;

    System.Console.WriteLine("Starting server...");
    server.Start();
}

private static void Server_OnStarting (object sender, EventArgs e)
{
    System.Console.WriteLine("Server_OnStarting.");
}

private static void Server_OnStarted (object sender, EventArgs e)
{
    System.Console.WriteLine("Server_OnStarted.");
}
Run Code Online (Sandbox Code Playgroud)

服务器启动方法:

public bool Start ()
{
    bool result = false;

    lock (this._SyncRoot)
    {
        if (!this.Running)
        {
            this.Stopwatch.Reset();

            this.RaiseOnStarting();

            this.Running = true;
            this.Terminate = false;
            this.ThreadObject = new System.Threading.Thread(new System.Threading.ThreadStart(this.ProcessInternal));

            this.Stopwatch.Restart();
            this.ThreadObject.Start();

            this.RaiseOnStarted();

            result = true;
        }
    }

    return (result);
}
Run Code Online (Sandbox Code Playgroud)

输出

控制台输出

在 3 个Console.WriteLine调用中Main,只有第一个被立即打印出来。这是可以理解的,因为所有内容都Database.Context.Initialize发生在同一线程上。然而,印刷Creating server...Starting server...被延迟,并与聚集在一起Server_OnStartingServer_OnStarted消息。对构造函数的调用不是线程化的,而是对 server.Start 的调用在内部启动一个线程,初始化一些套接字等。但是,事件OnStartingOnStarted同一线程上触发,因此它的线程化方面不应该重要。

似乎在Initializing context...打印之后,无论我在哪里调用Console.WriteLine,它都不会更新控制台窗口,直到 server.Start 在触发两个事件后返回。

有没有办法在等待服务器启动时强制控制台更新?

drf*_*drf 5

有没有办法在等待服务器启动时强制控制台更新?

默认情况下,控制台以这种方式运行;事实上,没有(受支持的)机制可以强制它以不同的方式运行。当Console.Out 属性启动时,AutoFlush底层的属性TextWriter设置为true。的文档AutoFlush明确指出这一点(强调):

例如,将 AutoFlush 设置为 true,当您写入用户希望立即获得反馈的设备时。Console.Out 是以下情况之一:在每次调用 StreamWriter.Write 后,内部用于写入 Console 的 StreamWriter 会刷新除编码器状态之外的所有内部状态。

(注意AutoFlush不能直接查询,因为实际实现使用线程安全包装器;但是,您可以使用调试器或反射来检查 的值是否((Console.Out as TextWriter.SyncTextWriter)._out as StreamWriter).AutoFlush为真。)


回到原来的问题:

似乎,在 Initializing context... 被打印之后,无论我在哪里调用Console.WriteLine,它都不会更新控制台窗口,直到server.Start在触发两个事件后返回。

让我们看看Server.Start实际做了什么:

  1. 进入锁(可能是非阻塞的,因为服务器没有启动)
  2. ** 引发 OnStarting 事件**
  3. 启动一个线程
  4. 重新启动秒表
  5. ** 引发 OnStarted 事件**
  6. 退货

这些任务都不是特别密集。OnStarting 和 OnStarted 调用之间的延迟可能在微秒范围内。

这三个状态消息似乎是同时打印的,因为在服务器实例化、进入Server.Start方法和从Server.Start方法返回之间没有明显的时间流逝。