Question:
Good afternoon. There is such a problem: I am writing a console chat. However, there is one unpleasant bug: if the user writes a message and at that moment a message arrives, the already entered data will be overwritten. The client expects input from the Console.ReadLine function. The question is: how can you get the already entered data and how to get it back? PS Messages come from one thread and the input function works on another thread
Answer:
If you use normal line-by-line I / O in the console, then nothing.
But there is a solution. You will have to control the cursor position and the positions for input and output yourself.
The easiest option is to display messages on the top lines of the visible portion of the console buffer, and text input on the bottom.
As promised, I am adding details of the implementation.
To control the position of the cursor in the console, you need the Console.SetCursorPosition(x,y)
method. The default display size for the console screen is 80×25 characters. But it can be customized. True, there is one caveat: you can increase the size on the go, at any time the program is running, and reduce it only by the system settings of the console before starting the program; in this case, changes made during the execution of the program are not remembered after its completion. The coordinate system is standard – the upper left corner has coordinates (0,0).
You will also have to abandon Console.Read/Readline
in favor of Console.ReadKey(true)
to disable echoing of entered characters.
Now you need to organize two output buffers, one for incoming messages, the other for user-typed messages, yes, we also do the output of what the user entered by hand. The size of the buffers is calculated so that when outputting to the console using the standard Console.Write/WriteLine
output lines in the console window are not jumbled. We create a buffer based on a StringBuilder
with an explicit size indication. If the output text is less than the buffer, we pad it with spaces to overwrite the previous output when outputting.
We receive messages in a separate buffer from which we fill the output buffer with the last received messages.
Then everything is quite simple, when a new message arrives, we put the cursor in position (0,0) and display the received messages, if the user started typing a message, we display its text as he type at the bottom of the screen, for example, to position (0.20). The main program loop boils down to two actions – displaying received messages, if any, and displaying a character entered by the user, if the user has entered it. In the case of a multi-threaded solution, you can limit yourself to checking the flags about the need for output and output.
In principle, with a certain amount of perseverance, you can organize the scrolling of received messages, but we handle the pressed keys with our hands, so everything is in your hands.
In general, this concept is quite enough for implementation in code; examples of individual actions are easy to find in MSDN in the description of the Console
class