Please read the answer by Scott Chamberlain to see why is it related to WINAPI.
Create a new WPF application in Visual Studio and change the code in MainWindow.xaml.cs
as below. Run the application. The code will hang on second call to Console.Write()
.
MainWindow.xaml.cs
using System;
using System.Text;
using System.Windows;
namespace TestWpf
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
byte[] msg = new byte[1024];
string msgStr = Encoding.Default.GetString(msg);
for (int i = 0; i < 10; i++)
{
Console.Write(msgStr);
}
}
}
}
Now create a new Console application in Visual Studio and change the code in Program.cs
as below. Run the application. It will run successfully i.e. it will not hang.
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
byte[] msg = new byte[1024];
string msgStr = Encoding.Default.GetString(msg);
for (int i = 0; i < 100; i++)
{
Console.Write(msgStr);
}
}
}
}
Questions:
\0
? (It works fine if you do 1024 spaces.)The first solution is to run the application without debugging by using Ctrl+F5 instead of just F5. The console window will remain open when the program has finished.
While Write() and WriteLine() both are the Console Class methods. The only difference between the Write() and WriteLine() is that Console. Write is used to print data without printing the new line, while Console. WriteLine is used to print data along with printing the new line.
The WriteConsole function writes characters to the console screen buffer at the current cursor position. The cursor position advances as characters are written.
Press F5 to run the program in Debug mode. Another way to start debugging is by choosing Debug > Start Debugging from the menu. Enter a string in the console window when the program prompts for a name, and then press Enter . Program execution stops when it reaches the breakpoint and before the Console.
Basic Explanation: It hangs because the buffer Console.Write
writes to before the text is displayed is getting full and is not draining out for WPF applications when passing in null characters (\0
) for reasons beyond my knowledge.
Detailed Explanation: When you call Console.Write
it creates a Handle to output it's data to and eventually calls WriteFile
on that handle. The other end of the handle needs to process the data that was written to it then return control to the caller. There are two major differences between WPF and a console application I could find:
First, if you inspect the handle type with a console application you get a handle of type FILE_TYPE_CHAR
, from WPF you get FILE_TYPE_PIPE
.
Console.Write(msgStr);
var cOut = Console.OpenStandardOutput();
var handle = cOut.GetType().GetField("_handle", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(cOut);
var method = Type.GetType("Microsoft.Win32.Win32Native").GetMethod("GetFileType", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
var type = method.Invoke(null, new object[] { handle });
Debugger.Break();
Second, how the handle is processed on the receiving end is different. In a console application the handle is read in by conhost.exe
, in WPF it is read in by visual studio.
The hang itself comes from the fact that there is limited space in the buffer and only so much text can be queued up before the handle has to block new incoming requests so the existing information can drain out. It appears that the handle for the console application can process large numbers of \0
characters but the handle that WPF generates can not. If that difference is from it being a different kind of handle or from the processor on the other side of the handle reading in data differently I don't know.
Hopefully someone who has more experience than me with the Windows API call WriteFile
that can explain the differences between the two handle types and will give us a better idea if this is because of the handle type or because of the receiving program.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With