Home > Enterprise >  Unsynchronized printed messages when working with multiple threads
Unsynchronized printed messages when working with multiple threads

Time:12-16

I'm writing some sort of terminal chat application that has a very simple interface:

[Me] Here I write my messages.
[Me] When the Enter key is pressed, the message is sent to other users.
[user1] Other users can also send me messages.
[user2] Their usernames are shown at the start of the line, between square brackets.

This application's main thread just waits until the user writes a message and presses Enter:

msg = input('[Me] ')
# Do stuff with msg...

And received messages from other users are shown in the screen with a simple print function call (that runs in other thread):

print(f'\n[{msg_author}] {msg_content}')

Thing is I'm not able to deal with the printing of messages received from other users in a pretty way. For example, after a new message is received, the state of the screen may be the next one:

[Me]
[user1] New message appeared!

Since the print function ran because of the new message, now the app is still waiting for me to write a message, but the cursor is in a new line (note the last blank line), so if I start to write a message, it will be shown like this

[Me]
[user1] New message appeared!
I'm writing here...

when the prettier way will be that the screen updates to

[user1] New message appeared!
[Me] This will be the way!

This is even a bigger problem when I have wrote some part of my new message (without pressing Enter) and a new message is received:

[Me] I have still not finished this message...
[user1] Another message appeared!

The message I was writing should be shown like this:

[user1] Another message appeared!
[Me] I have still not finished this message... And I would like to continue it down here!!!

I'm aware of the existence of CSI sequences, but I believe they don't help to solve this problem (actually, I don't even know if this is solvable using the input function to ask for messages).

CodePudding user response:

You will have a hard or impossible time with this just using input and print. Suggest you look at either of these:

CodePudding user response:

You appear to be writing a "console application." The first thing you need to know is that the console is not part of your application. It is an entirely independent thing that communicates with your application through "pipes." The console is an emulation of a computer terminal from back in the 20th century, and computer terminals originally were not designed for an application that could produce output asynchronously with awaiting input.

IMO you have two options. The better one is to build a full-on GUI app instead of a console app. For that, you'll want to use a GUI framework such as PyQt5, WxPython, etc. Unfortunately, if you have not yet done any GUI programming, then you've got a lot of learning ahead of you before you get to the point of being able to create a chat-like GUI that works as smoothly as the messaging app on your smartphone.

The other option is to build a console application that uses ANSI escape sequences to create a somewhat GUI-like user experience. I would strongly encourage you to use a 3rd party library such as ncurses to help with that. There's still going to be somewhat of a learning curve, but maybe not as steep.

IMO: For a first cut at using ncurses, I would divide the console screen into two windows; A small one at the bottom where the local user can edit their next message, and a bigger one that fills the rest of the screen where the local user can see their previous messages interleaved with messages from remote users.

I haven't done enough with ncurses myself to be able to show you any example code. But maybe you can find examples out there on the Interwebs.

  • Related