0

Once, when I used the cw snippet (type cwTAB) in an async method, Visual Studio would use await Console.Out.WriteLineAsync(); instead of the original Console.WriteLine();. Today I updated Visual Studio to 17.10 and noticed that the snippet produces Console.WriteLine(); in async methods.

Due to this behavior in the past, I have been using await Console.Out.WriteLineAsync(); in asynchronous methods, so initially I thought it might be a bug. But after actual testing, I did not find any problems with using Console.WriteLine(); in asynchronous methods.

I would like to ask, is there any difference between these two methods? If there is no difference, why did Visual Studio recommend await Console.Out.WriteLineAsync(); in old versions?


According to @PanagiotisKanavos' comments, if a large amount of tasks are used in the code, Console.Out.WriteLineAsync(); is sometimes faster, but in most cases, the performance of both is almost the same.

[Benchmark]
public async ValueTask Benchmark1()
{
    await Parallel.ForAsync(0, 50, async (i, ct) =>
    {
        await Console.Out.WriteLineAsync(LONGTEXT);
        await Job();
        await Console.Out.WriteLineAsync("short_text");
    });
}

[Benchmark]
public async ValueTask Benchmark2()
{
    await Parallel.ForAsync(0, 50, async (i, ct) =>
    {
        Console.WriteLine(LONGTEXT);
        await Job();
        Console.WriteLine("short_text");
    });
}

public async static ValueTask Job()
{
    for (int i = 0; i < 12950; i++)
        await Task.Yield();
}
13
  • 3
    The bottleneck here is I/O through the console which acquires locks. It's a poor place to look to improve performance. Commented Jul 4 at 6:31
  • 5
    Async is not about doing specific things faster, it is about freeing up resources to do other things instead of waiting around for I/O (like writing to the console stream, which might be blocked by other calls to write to it). In most cases async will be slower due to the overhead needed. Commented Jul 4 at 6:34
  • 2
    This isn't a good benchmark and the results are bogus. First of all, it launches 200 async void delegates, which can't be awaited. That means Benchmark1 can easily finish before the lines are written. Second, only one thing can be written to the console otherwise the output would be jumbled. This restriction is enforced by .NET and I suspect, the OS itself. It doesn't if the console is accessed through a TextWriter or as a Stream Commented Jul 4 at 6:45
  • 1
    TextWriter.WriteLineAsync doesn't write to the output faster. Like all async IO, it avoids blocking the caller thread while an IO operation is going on. In a desktop app that means the UI thread can draw the UI instead of freezing. In a web app it means the thread can process other requests. The necessary synchronization through callbacks/IO completion ports means async operations are slightly slower than sync. Commented Jul 4 at 6:49
  • 1
    To the visitors: the comments cannot be curated by the community and cannot be downvoted. In case there is misinformation in the comments, as is the case with some comments above, the only thing we can do is to flag them and hope that the moderators will delete them. So don't look for answers in the comments. Look at the actual answers under the question. These answers can be discussed, curated and downvoted, so they are much more reliable than the comments. Commented Jul 4 at 9:48

4 Answers 4

3
+200

I found the actual answer after going through the source in GitHub and realizing Console.Out.WriteLineAsync makes no sense (Out is a synchronized TextWriter). A last Google search for Console.Out.WriteLineAsync after going through the source returned a discussion in the Semantic Snippets GH issue in the Roslyn repository

It was changed back to Console.WriteLine because as Stephen Toub wrote in the issue discussion

Console.Out is always a synchronized text writer (TextWriter.Synchronized), with all operations guarded by a Monitor; all operations that write to the console are guarded by the same lock, and any time we've tried to change that, we've had to revert because significant numbers of apps have taken dependencies on being able to do things like lock (Console.Out) { Console.ForegroundColor = ...; ... multiple writes ...; Console.ResetColor(); }. Async operations on such a writer get converted into synchronous ones. Using await Console.Out.WriteLineAsync(...) instead of Console.WriteLine(...) has no upside and only overhead / more complicated code.

In the Semantic Snippets GH issue neuecc pointed out in 2023 that WriteLineAsync is unnecessary:

In the latest Visual Studio, cw has become Console.Out.WriteLineAsync at async context, but I think this is unnecessary.

It is a bad feature unless it is reverted back to Console.WriteLine or made configurable.

Because

ConsoleStream only has sync write. https://source.dot.net/#System.Console/System/IO/ConsoleStream.cs,c0e0ba628fa4c224

UnixConsoleStream: https://source.dot.net/#System.Console/System/ConsolePal.Unix.ConsoleStream.cs,13bf065fbb4646d5

WindowsConsoleStream: https://github.com/dotnet/runtime/blob/f9f7f8079377039a8d42269434a41ca55d14d591/src/libraries/System.Console/src/System/ConsolePal.Windows.cs#L1076

In other words, I don't think Async makes sense.

Further down he also points out that Console.Out is a synchronized text writer that performs async operations synchronously and returns a completed task

[MethodImpl(MethodImplOptions.Synchronized)]
public override Task WriteLineAsync()
{
    WriteLine();
    return Task.CompletedTask;
}

BTW I never wrote that async will be faster. If anything, it can be slightly slower due to the generated state machine and callbacks if async operations are actually performed. If the code executes synchronously, we pay the cost of the state machine for no benefit. It's the only overhead / more complicated code case that Stephen Toub talks about

0
1

In terms of performance, the difference is likely negligible because writing text to the console is very fast. Personally, I would say Console.WriteLine should be used over Console.Out.WriteLineAsync. As tested, Console.Out.WriteLineAsync is sometimes faster by a few microseconds or so, but not always.

Because both write to the console, there is no visible difference between Console.WriteLine and Console.Out.WriteLineAsync.

The Console.Out property is a static TextWriter that opens the console handle and writes text there. Every Write and WriteAsync method will instead write to the console.

When you invoke the Console.WriteLine method, it instead invokes Console.Out.WriteLine, and since every Write method in the Console.Out property writes directly to the console, well, it writes a new line to the console.

However, TextWriter also has .WriteLineAsync methods (aside from other asynchronous write methods). Since anything could inherit from TextWriter, there needs to be a way to write text asynchronously as well. So, Console.Out.WriteLineAsync simply writes text with a new line to the console and is implemented because it's a part of TextWriter.

Generally, there is most likely no difference, since both write to the console. .WriteLineAsync is implemented because it has to be implemented, since it's a method that overrides from TextWriter.

In synchronous and asynchronous methods, I would personally recommend to use Console.WriteLine.

Besides from the technical differences, one another difference includes the fact that Console.Out.WriteLineAsync is not widely used.

See TextWriter Methods.

The problem with Visual Studio 2022 'cw' snippet

From what I understand, an older version of Visual Studio 2022 would insert await Console.Out.WriteLineAsync in an async method instead of Console.WriteLine, which has changed after the update. Visual Studio 2022 really does do so (17.9.6).

I'm not really sure why it was removed, because there seems to be no information on the internet. For the removal, I'm assuming because await Console.Out.WriteLineAsync isn't commonly used anymore and it is pretty much the same thing as Console.WriteLine, but not sure about why VS recommended it earlier.

If you want to convert all await Console.Out.WriteLineAsync calls to Console.WriteLine throughout the codebase (whether it's a project or solution), press Ctrl + Shift + H to bring the Replace in Files dialog to replace await Console.Out.WriteLineAsync with Console.WriteLine.

2
  • What I don't understand is that since they are the same, why was await Console.Out.WriteLineAsync recommended in the previous Visual Studio version?
    – shingo
    Commented Jul 4 at 13:15
  • @shingo Edited answer to include that information Commented Jul 4 at 14:29
0

There is absolutely no difference between the Console.WriteLine() and the await Console.Out.WriteLineAsync(). The Console.Out.WriteLineAsync always returns a completed Task. It is always a synchronous operation:

Task task = Console.Out.WriteLineAsync();
Console.WriteLine(task == Task.CompletedTask);

Output:


True

Online demo.

When the Console.Out.WriteLineAsync() returns, the text has been already printed in the console. There is no asynchronous dimension. There is no thread-switch. All work is performed synchronously on the current thread.

Any minuscule performance difference that you might have observed, can be attributed to minor flaws in the benchmark methodology, or to random factors. There is no reason for the one approach to be faster than the other. Both are doing exactly the same thing, in exactly the same way.

2
  • What I don't understand is that since they are the same, why was await Console.Out.WriteLineAsync recommended in the previous Visual Studio version, but changed to Console.WriteLine in the latest version?
    – shingo
    Commented Jul 4 at 13:14
  • @shingo honestly I have no idea. I have spend too much time of my life changing the severity of various .NET diagnostics to None, to get rid of the visual hints that VS doesn't like my code. Commented Jul 4 at 14:26
-2

If you look into decompiled source of Console.WriteLine you'll see

[MethodImpl(MethodImplOptions.NoInlining)]
public static void WriteLine() => Console.Out.WriteLine();

So, it's basically the same. Console suports writing into main streams In, Out, Err. I think that Console.WriteLine is just a convient wrapper to write into Out, because it's most commonly used

2

Not the answer you're looking for? Browse other questions tagged or ask your own question.