freefrag
asked on
Multithreaded console
Hey!
I want to create a simple multithreaded application in the console
that will display some data while reading data from the user
However I have ran into some trouble.
If one of my threads calls Console.Writeline(), both what the user has typed in and what my program typed in will be displayed at once.
is there any way to store what the user has typed in, display the message
then restore it back to the console?
I want to create a simple multithreaded application in the console
that will display some data while reading data from the user
However I have ran into some trouble.
If one of my threads calls Console.Writeline(), both what the user has typed in and what my program typed in will be displayed at once.
is there any way to store what the user has typed in, display the message
then restore it back to the console?
Can you post your code? Sounds like you either need some thread synchronization, or are echoing characters back to the console in addition to .Net also echoing the typed characters.
ASKER
static void Main(string[] args)
{
TextWriter txt = null;
Thread Spam = new Thread(new ThreadStart(SPPPPPAM));
Thread Read = new Thread(new ThreadStart(READDDD));
Read.Start();
Spam.Start();
}
static void READDDD()
{
while (true)
{
string s = string.Format("rrright, so thats what you ment: {0}", Console.ReadLine());
Console.WriteLine(s);
}
}
static void SPPPPPAM()
{
while (true)
{
Console.WriteLine("Spammin ");
Thread.Sleep(1000);
}
}
{
TextWriter txt = null;
Thread Spam = new Thread(new ThreadStart(SPPPPPAM));
Thread Read = new Thread(new ThreadStart(READDDD));
Read.Start();
Spam.Start();
}
static void READDDD()
{
while (true)
{
string s = string.Format("rrright, so thats what you ment: {0}", Console.ReadLine());
Console.WriteLine(s);
}
}
static void SPPPPPAM()
{
while (true)
{
Console.WriteLine("Spammin
Thread.Sleep(1000);
}
}
HI,
Try using Lock like below,
static void READDDD()
{
private System.Object lockThis = new System.Object();
while (true)
{
Lock(lockThis)
{
string s = string.Format("rrright, so thats what you ment: {0}", Console.ReadLine());
Console.WriteLine(s);
}
}
}
refer this msdn link
http://msdn.microsoft.com/en-us/library/ms173179%28VS.80%29.aspx
Regards
Deepu
Try using Lock like below,
static void READDDD()
{
private System.Object lockThis = new System.Object();
while (true)
{
Lock(lockThis)
{
string s = string.Format("rrright, so thats what you ment: {0}", Console.ReadLine());
Console.WriteLine(s);
}
}
}
refer this msdn link
http://msdn.microsoft.com/en-us/library/ms173179%28VS.80%29.aspx
Regards
Deepu
ASKER
doesnt work probably because the console buffer is a shared resource
I believe both threads need to refer to the same object in order for locking to work, so something like this (sorry, not exactly sure how you intended this to run, or what you're trying to accomplish, but this does demonstrate thread sync using a lock):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication2
{
class Program
{
static Object lckObj = new Object();
static void Main(string[] args)
{
Thread Spam = new Thread(new ThreadStart(SPPPPPAM));
Thread Read = new Thread(new ThreadStart(READDDD));
Read.Start();
Spam.Start();
}
static void READDDD()
{
while (true)
{
lock (lckObj)
{
Console.Write("Enter some text: ");
string s = Console.ReadLine();
Console.WriteLine("You entered {0}", s);
}
}
}
static void SPPPPPAM()
{
while (true)
{
lock (lckObj)
{
Console.WriteLine("Spammin");
}
Thread.Sleep(1000);
}
}
}
}
ASKER
nope, still isnt working.
Now it doesnt type the text until the user presses enter
Now it doesnt type the text until the user presses enter
Hi,
Please refer the EE Link,
https://www.experts-exchange.com/questions/23113014/Console-Application-with-Multi-Threading.html
Regards
Deepu
Please refer the EE Link,
https://www.experts-exchange.com/questions/23113014/Console-Application-with-Multi-Threading.html
Regards
Deepu
Well, like I said I'm not sure how you intended for this to run. The code in your question is kinda like two different programs both running simultaneously on the same console with complete disregard for each other, i.e. if the 1,000ms Sleep() in thread 2 happens to expire while the user is entering text into thread 1's ReadLine() it's not gonna know, or care, and will happily insert "spammin" into whatever the user is typing.
My example uses the lock, so that 1 thread waits for the other, before thread 1 attempts to read anything from the user it locks lckObj, which causes thread 2 to wait until the lock is released - which happens after Console.ReadLine(), i.e. when the user presses enter - this way thread 2 is not inserting text into the console while thread 1 is trying to have the user enter input. Because thread 1 has no delay, as soon as a user enters text it's prompting for another line, it has the effect of alternating lines of user text & "spammin."
Put a 5 second delay in the READDD loop.
My example uses the lock, so that 1 thread waits for the other, before thread 1 attempts to read anything from the user it locks lckObj, which causes thread 2 to wait until the lock is released - which happens after Console.ReadLine(), i.e. when the user presses enter - this way thread 2 is not inserting text into the console while thread 1 is trying to have the user enter input. Because thread 1 has no delay, as soon as a user enters text it's prompting for another line, it has the effect of alternating lines of user text & "spammin."
Put a 5 second delay in the READDD loop.
Add Thread.Sleep(5000) in READDD thread *outside* the lock block.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication2
{
class Program
{
static Object lckObj = new Object();
static void Main(string[] args)
{
Thread Spam = new Thread(new ThreadStart(SPPPPPAM));
Thread Read = new Thread(new ThreadStart(READDDD));
Read.Start();
Spam.Start();
}
static void READDDD()
{
while (true)
{
lock (lckObj)
{
Console.Write("Enter some text: ");
string s = Console.ReadLine();
Console.WriteLine("You entered {0}", s);
}
Thread.Sleep(5000);
}
}
static void SPPPPPAM()
{
while (true)
{
lock (lckObj)
{
Console.WriteLine("Spammin");
}
Thread.Sleep(1000);
}
}
}
}
Maybe this is what you wanted.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication3
{
class Program
{
static Object lckObj = new Object();
static void Main(string[] args)
{
Thread inputThread = new Thread(InputThreadProc);
Thread outputThread = new Thread(OutputThreadProc);
inputThread.Start();
outputThread.Start();
}
static void InputThreadProc()
{
StringBuilder userInput = new StringBuilder();
while (true)
{
if (Console.KeyAvailable)
{
char inputChar = Console.ReadKey(true).KeyChar;
if ((inputChar == '\r') || (inputChar == '\n'))
{
lock (lckObj)
{
Console.WriteLine("User entered: {0}", userInput.ToString());
userInput.Remove(0, userInput.Length);
}
}
else
userInput.Append(inputChar);
}
else
Thread.Sleep(125);
}
}
static void OutputThreadProc()
{
string outputText = "Hello World";
while (true)
{
lock (lckObj)
{
Console.WriteLine(outputText);
}
Thread.Sleep(1000);
}
}
}
}
ASKER
still not working.
it stops to let you type in the text, and this is no what I want it to do.
I want the whole program to continute Writing to the console, but allowing the user to input text at the same time. so for example the current output is
Spam
Spam
Spam
Spam
asd
where asd is what the user typed in.
If at the same time the other thread writes a line this is what will happen
Spam
Spam
Spam
Spam
asdSpam
and what I want it to do is
Spam
Spam
Spam
Spam
Spam
asd
so that it adds a line and doesnt delete what the user typed in
it stops to let you type in the text, and this is no what I want it to do.
I want the whole program to continute Writing to the console, but allowing the user to input text at the same time. so for example the current output is
Spam
Spam
Spam
Spam
asd
where asd is what the user typed in.
If at the same time the other thread writes a line this is what will happen
Spam
Spam
Spam
Spam
asdSpam
and what I want it to do is
Spam
Spam
Spam
Spam
Spam
asd
so that it adds a line and doesnt delete what the user typed in
In my most recent snippet, on line 30, change true to false. This will cause the users keystrokes to be displayed on-screen admidst all the "Spammin's", and once the user presses the Enter key, a clean line is output.
Can you Just try a Console.Clear() just after the Second Thread.
Sorry I mean Console.Out.Flush()
This is the type of output you're expecting? Note that the bold characters are what I typed, and notice how - since both threads are using the console simultaneously - "Hello World" occurs in the middle of whatever I was typing, until I press enter then thread 1 causes thread 2 to pause, outputs whatever I entered, then lets thread 2 resume.
Hello World
ThHello World
e quickHello World
brownHello World
fox juHello World
mped oveHello World
r the laHello World
zy dogHello World
User entered: The quick brown fox jumped over the lazy dog.
Hello World
Hello World
Hello World
ThHello World
e quickHello World
brownHello World
fox juHello World
mped oveHello World
r the laHello World
zy dogHello World
User entered: The quick brown fox jumped over the lazy dog.
Hello World
Hello World
ASKER
no this is what I was expecting
h
//new line
HelloWorld
hey
//new line
HelloWorld
HelloWorld
hey there
//new line
HelloWorld
HelloWorld
HelloWorld
hey there!
//user pressed enter
HelloWorld
HelloWorld
HelloWorld
You typed in: hey there!
h
//new line
HelloWorld
hey
//new line
HelloWorld
HelloWorld
hey there
//new line
HelloWorld
HelloWorld
HelloWorld
hey there!
//user pressed enter
HelloWorld
HelloWorld
HelloWorld
You typed in: hey there!
Hmm, this code seems a little overly complex to me, but I think it does what you want. ;)
Hello World
Hello World
Th
Hello World
The
Hello World
Hello World
The quick
Hello World
The quick brow
Hello World
The quick brown
Hello World
Hello World
Hello World
The quick brown fox ju
Hello World
The quick brown fox jumped ov
Hello World
The quick brown fox jumped over the la
Hello World
The quick brown fox jumped over the lazy do
Hello World
User entered: The quick brown fox jumped over the lazy dog.
Hello World
Hello World
Some
Hello World
Something
Hello World
Something else
Hello World
Something else.
Hello World
User entered: Something else.
Hello World
Hello World
Hello World
Hello World
Hello World
Th
Hello World
The
Hello World
Hello World
The quick
Hello World
The quick brow
Hello World
The quick brown
Hello World
Hello World
Hello World
The quick brown fox ju
Hello World
The quick brown fox jumped ov
Hello World
The quick brown fox jumped over the la
Hello World
The quick brown fox jumped over the lazy do
Hello World
User entered: The quick brown fox jumped over the lazy dog.
Hello World
Hello World
Some
Hello World
Something
Hello World
Something else
Hello World
Something else.
Hello World
User entered: Something else.
Hello World
Hello World
Hello World
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication3
{
class Program
{
static Object consoleOutputLock = new Object();
static Object boolLock = new Object();
static Object stringLock = new Object();
static bool newKeysEntered = false;
static StringBuilder userInput = new StringBuilder();
static void Main(string[] args)
{
Thread inputThread = new Thread(InputThreadProc);
Thread outputThread = new Thread(OutputThreadProc);
inputThread.Start();
outputThread.Start();
}
static void InputThreadProc()
{
while (true)
{
if (Console.KeyAvailable)
{
char inputChar = Console.ReadKey(true).KeyChar;
if ((inputChar == '\r') || (inputChar == '\n'))
{
lock (boolLock) { newKeysEntered = false; }
lock (consoleOutputLock)
{
lock (stringLock)
{
Console.WriteLine("User entered: {0}", userInput.ToString());
userInput.Remove(0, userInput.Length);
}
}
}
else
{
lock (boolLock) { newKeysEntered = true; }
lock (stringLock) { userInput.Append(inputChar); }
}
}
}
}
static void OutputThreadProc()
{
string outputText = "Hello World";
bool alsoOutputUserText = false;
while (true)
{
lock (boolLock) { alsoOutputUserText = newKeysEntered; }
lock (consoleOutputLock)
{
if (alsoOutputUserText)
{
lock (boolLock) { newKeysEntered = false; }
lock (stringLock) { Console.WriteLine(userInput.ToString()); }
}
Console.WriteLine(outputText);
}
Thread.Sleep(1000);
}
}
}
}
ASKER
still not what I mean :/
instead of it displaying
Hello World
Some
Hello World
Something
Hello World
Something else
Hello World
Something else.
Hello World
User entered: Something else.
Hello World
Hello World
Hello World
I dont want to show what the user entered previously.
I just want the input to always be on the bottom of the console, regardless of how many lines the user entered.
Think of it as an internet messenger.
instead of it displaying
Hello World
Some
Hello World
Something
Hello World
Something else
Hello World
Something else.
Hello World
User entered: Something else.
Hello World
Hello World
Hello World
I dont want to show what the user entered previously.
I just want the input to always be on the bottom of the console, regardless of how many lines the user entered.
Think of it as an internet messenger.
ASKER
Maybe there is a way, to see and edit what the user types before he presses enter?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
well this isnt exactly what I wanted, but fair enough. You've done waaaay too much work for this to go unnoticed. You helped me realise what question I need to ask :)
thanks a lot
thanks a lot