I want to interrupt my producer-consumer program by pressing the key T. I searched a lot of answers but i can't figure out why it is not working.
static void Main(string[] args)
{
Buffer buffer = new Buffer();
Produtor prod = new Produtor(buffer);
Thread threadProdutor = prod.CriarThreadProdutor();
Consumidor cons = new Consumidor(buffer, 100000);
Thread threadConsumidor = cons.CriarThreadConsumidor();
threadProdutor.Start();
threadConsumidor.Start();
threadProdutor.Join();
threadConsumidor.Join();
while (Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.T)
{
Environment.Exit(0);
}
}
I added a breakpoint in my while, but the program won't even get there.
By putting the loop after your Join() calls the threads will have already completed by the time you check the console for input, so you'll need to reverse the order.
Further, the while loop will only be entered and continue running if there is a key available and it is T. You want the opposite: loop until a key is available and it is T.
Finally, Console.ReadKey() blocks until a key is pressed, so you don't need to check Console.KeyAvailable, too, unless you want to do something else while you wait for T (such as display progress or check if the threads completed on their own).
while (Console.ReadKey(true).Key != ConsoleKey.T)
{
// Do nothing...
}
// T has been pressed
// Signal to the threads to stop
// Set a flag, Cancel() a CancellationTokenSource, etc.
// Wait for the threads to terminate
threadProdutor.Join();
threadConsumidor.Join();
// Exit the program
Environment.Exit(0);
To display progress while you wait for the interrupt key, you can rewrite the loop like this...
TimeSpan progressInterval = TimeSpan.FromSeconds(1);
// complete is a simple flag set by the consumer(s)
// Only call ReadKey() when KeyAvailable so it can't block longer than updateInterval
while (!complete && (!Console.KeyAvailable || Console.ReadKey(true).Key != ConsoleKey.T))
{
Console.WriteLine($"Current time is {DateTime.Now:HH:mm:ss.fff}");
Thread.Sleep(progressInterval);
}
Note that this has the downside of always sleeping for the entire progressInterval, even if the exit condition has been satisfied before then. A simple workaround would be to reduce the time between checks to 1 / n and then only display the progress after every nth check...
TimeSpan progressInterval = TimeSpan.FromSeconds(1);
const int ReadsPerProgressInterval = 10;
TimeSpan sleepTimeout = new TimeSpan(progressInterval.Ticks / ReadsPerProgressInterval);
int readCount = 0;
// complete is a simple flag set by the consumer(s)
// Only call ReadKey() when KeyAvailable so it can't block longer than updateInterval
while (!complete && (!Console.KeyAvailable || Console.ReadKey(true).Key != ConsoleKey.T))
{
// This won't display progress until after progressInterval has elapsed
// To display initial progress:
// A) change to == 1, or...
// B) duplicate progress display to before the loop as well
if (++readCount % ReadsPerProgressInterval == 0)
Console.WriteLine($"Current time is {DateTime.Now:HH:mm:ss.fff}");
Thread.Sleep(sleepTimeout);
}
Related
Task description:
Write a program that reads an positive integer value n (n > 3), then
creates n threads (each thread has id; id starts from 1) and works
until it receives a stop signal. All of n threads are waiting for a
signal. Every second main thread sends a signal for a random thread,
then that thread should print its id and return to a waiting state.
Requirements:
All additional threads should be finished correctly. At the thread
function exit, a message about exit should be printed. While the
thread is waiting for the condition variable, spurious wakeup should
be checked. Only std::cout allowed for text output. Stop signal is
SIGINT (ctrl+c).
I have written the following code for the above question but in output, all the threads are not exiting. I am not able to figure out the problem as I am new to this topic. Any kind of help will be really appreciated.
class Program
{
public static void Main()
{
var numberofthreads = Convert.ToInt32(Console.ReadLine());
ProcessingClass myobject = new ProcessingClass();
myobject.createThreads(numberofthreads);
}
}
public class ProcessingClass
{
public Mutex mymutex = new Mutex();
private bool thread_flag = false;
public void createThreads(int numberofthreads)
{
var threads = new List<Thread>(numberofthreads);
for (int i = 0; i < numberofthreads; i++)
{
Thread th = new Thread(() =>
{
threadsworking();
});
th.Name = "Thread" + i;
th.Start(); // <-- .Start() makes the thread start running
threads.Add(th);
}
Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs e) =>
{
var isCtrlC = e.SpecialKey == ConsoleSpecialKey.ControlC;
if (isCtrlC)
{
thread_flag = true;
int num = 1;
foreach (var thread in threads)
{
thread.Join();
Console.WriteLine($"Thread {num} exits");
num++;
}
}
e.Cancel = true;
};
}
public void threadsworking()
{
while (thread_flag == false)
{
mymutex.WaitOne(); // Wait until it is safe to enter.
Console.WriteLine("{0}", Thread.CurrentThread.Name);
Thread.Sleep(1000); // Wait until it is safe to enter.
mymutex.ReleaseMutex(); // Release the Mutex.
}
}
}
enter image description here
Consider preventing mutex from blocking threads from exiting.
When you use mutex.WaitOne() it blocks execution until the Mutex is owned by that thread. This can be really helpful for ensuring a thread has exclusive control over a shared resource. However, where this becomes a problem is when you want to arbitrarily end those threads such as when you invoke the event on the Console.CancelKeyPress.
You can see the effects of this by logging before and after the thread.Join() call you do in the event.
thread_flag = true;
int num = 1;
foreach (var thread in threads)
{
Console.WriteLine($"Joining {thread.Name}");
thread.Join();
Console.WriteLine($"Joined {thread.Name}");
Console.WriteLine($"Thread {num} exits");
num++;
}
When we do that logging it will show us that when you call Join() on Thread # 1 you see Joining 1. Then there is a really long pause, other threads still are doing work, and then finally all the threads join back to back.
The reason for this is - while Join() is waiting for Thread 1 to finish, Thread 1 is still waiting for the mutex.
Even though you set the thread_flag flag to true, Thread 1 can't exit because it hasn't taken ownership of the mutex to perform it's work and eventually exit the while() loop.
We can solve this issue fairly simply.
Consider using a timeout when waiting for the mutex
When you call .WaitOne(n) on the mutex you can wait for n given milliseconds and give up taking ownership of the mutex.
This will allow more frequent evaluations of the while loop, and subsequently more times that the threadsworking method checks to see if it should exit(using the thread_flag flag).
Heres a short example how implementing that change might look
public void threadsworking()
{
while (thread_flag == false)
{
// wait to enter the mutex, give timeout to prevent blocking
// until mutex opens and use the bool returned to determine
// if we should release the mutex or not
if (mymutex.WaitOne(1))
{
try
{
Console.WriteLine("{0}", Thread.CurrentThread.Name);
Thread.Sleep(1000); // Wait until it is safe to enter.
}
finally
{
// make sure even if we encounter an error the mutex is released
mymutex.ReleaseMutex(); // Release the Mutex.
}
}
// allow other threads to continue their work instead of blocking with a while loop, this is optional depending on the workload
Thread.Yield();
}
}
I'm in the process of writing a simple "Score Attack" Poker game. A player assembles poker hands which are worth points as a timer ticks down. My problem is a game over scenario.
My game logic runs in a single thread since the game itself is so simple. I need to know how to terminate that thread as it is, with the player no longer able to make input. I've read on the MSDN that the safe way to do this is to use a loop to cause the thread's method to return and end the thread. The problem I run into is that my game requires user input, and the user input would cause the loop to not be checked at the moment the timer ticks to zero.
The code so far uses the Thread.Abort(), and it works, but from my searching on this site that is universally regarded as a bad idea. Is there any way I could set a condition that would terminate the thread safely regardless of methods within said thread needing input? (Console.ReadLine())
Code for the game loop and timer callback that aborts the thread:
private void GameLoop()
{
double stash = 0;
while (true)
{
player.SwapCards(gameDeck);
Table.WriteInfo("Stash This Hand? y/n");
if (Console.ReadLine().Equals("y"))
{
countdown += (int)ScoreHand(player.Hand);
stash += ScoreHand(player.Hand);
BankHand();
}
}
}
private void TimeDrop(object state)
{
countdown--;
Debug.WriteLine(countdown);
if (countdown == 0)
{
GameThread.Abort();
GameOverThread.Start();
Timer.Dispose();
}
}
As it sits the loop simply runs until the thread is aborted.
Edit:
Upon request, the code the starts the threads:
public Game()
{
gameDeck = new Deck();
InitPlayer();
DealHand();
countdown = 60;
GameThread = new Thread(GameLoop);
GameOverThread = new Thread(GameOver);
Timer = new Timer(new TimerCallback(TimeDrop), null, 0, 1000);
Timer.Change(0, 1000); //Ensures timer won't be garbage collected
GameThread.Start();
}
This sort of thing can be implemented easier and cleaner using async/await rather than threads.
First we need to wrap the blocking console input method with one that is cancellable (and async). The method polls the console using KeyAvailable and asynchronously delaying while checking the CancellationToken.
public static async Task<ConsoleKeyInfo> ReadKeyAsync(CancellationToken cancellationToken)
{
while (!Console.KeyAvailable)
{
await Task.Delay(100, cancellationToken);
}
return Console.ReadKey();
}
Now we can start this async method and pass a cancellation token from a CancellationTokenSource that will automatically cancel after a specific amount of time (10 seconds as an example).
public static async Task Main(string[] args)
{
Console.WriteLine("You have 10 seconds to press the Y key...");
var cts = new CancellationTokenSource(10_000);
try
{
while (true)
{
var key = await ReadKeyAsync(cts.Token);
if (key.Key == ConsoleKey.Y)
{
Console.WriteLine("Good job!");
break;
}
else
{
Console.WriteLine("Wrong Key");
}
}
}
catch (OperationCanceledException)
{
Console.Write("Time up!");
}
}
I have a console application with two threads, one is doing repetitive time consuming work, the other is checking to see if the user has pressed the ESC key. If the ESC key was pressed, the time consuming work thread is paused, an "are you sure" message appears, and if yes is selected, the time consuming work thread finishes its current loop then exits.
The code I have to check for a key-press is using a lot of CPU resources due to the while (!breakCurrentOperation(work)) ; loop. How can I prevent this from happening?
Code:
public void runTimeConsumingWork()
{
HardWork work = new HardWork();
Thread workerThread = new Thread(() => work.StartWorking());
workerThread.Start(); // Start the hard work thread
while (!workerThread.IsAlive) ; // Hault untill Thread becomes Active
// Check if the user wants to stop the hard work
while (!breakCurrentOperation(work)) ;
// Cancle the hard work
work.Stop();
// Notify the User
UserInterfaceController.WriteToConsole("Operation Cancled...");
}
public static bool breakCurrentOperation(HardWork work)
{
if (Console.KeyAvailable)
{
var consoleKey = Console.ReadKey(true);
if (consoleKey.Key == ConsoleKey.Escape)
{
work.Pause(); // Pause
UserInterfaceController.WriteToConsole("Do you want to stop the current process? \nType s to stop or c to continue.");
string input = Console.ReadLine();
if (input == "c" || input == "C")
{
work.Pause(); // Unpause
return false; // Continue
}
else if (input == "s" || input == "S")
{
return true; // Break the loop
}
else
{
UserInterfaceController.WriteToConsole("Error: Input was not recognized, the current process will now continue. Press Esc to stop the operation.");
work.Pause(); // Unpause
}
}
}
return false;
}
If I place a Thread.Sleep(2000) in the main console UI thread, CPU usage goes way down, but the application becomes unresponsive with a 2 second delay.
Do you really have to constantly poll for input? If you are waiting for input in a separate thread, just use the Console.ReadKey. It will block the input thread, but your other thread will keep processing. You don't seem to be doing anything else on the input thread, so blocking shouldn't be an issue.
Look like your esc key press check logic running in end less loop due to while loop. Due to this the function keep utilizing the system resource.
To overcome this please use some delay in your loop using Thread.Sleep. 1 second delay will improve lot of performance.
When the Deactivate event of window W1 is fired I want it to do it's go away & cleanup routine, unless the new foreground window is contained in a list of certain other windows. The other windows are all from the same process but run on different messagepump/GUI-threads. They are all winforms windows.
I created a Deactivate Routine that seems to be doing what I desire, but from the looks of it it feels like something to be ashamed of, so I wanted to ask you for a "cleaner" solution.
Explanation for the code sample posted below:
I lock because I believe I really don't want that monster to run twice at the same time under any circumstances.
I am doing the loop condition for the following reason:
foregroundWindowHandle is sometimes "0" instead of the handle of the window that is actually in foreground, unless I wait a few milliseconds (I tried 100) at the beginning of the Deactivate event. Since I am not sure those 100 ms guarantee me a not 0 foregroundWindowHandle I just wait until I can be sure it's not 0.
GetForegroundWindow() and GetWindowThreadProcessId() are the pInvoked methods of the same name.
Behold, my (working) attempt at solving this:
this.Deactivate += new EventHandler((a, b) =>
{
if (!Monitor.TryEnter(deactivateLockObject))
return;
try
{
while (true)
{
IntPtr foregroundWindowHandle = CSUTIL.GetForegroundWindow();
if (foregroundWindowHandle.ToString() == "0")
{
Thread.Sleep(1);
continue;
}
uint currentForegroundThreadId = CSUTIL.GetWindowThreadProcessId(foregroundWindowHandle, IntPtr.Zero);
if (new uint[] { threadidW1,threadidW2,threadidW3,etc. }.All((currentThreadId) => { return currentThreadId != currentForegroundThreadId; }))
this.MakeInvisible(); // Executes the closing & cleanup routine
break;
}
}
finally
{
Monitor.Exit(deactivateLockObject);
}
});
Ignoring programming style, here are some suggestions.
1) Your event handler may run in the main gui thread or another thread. If run on the gui thread, then "Sleep()" is inappropriate because it will prevent many other gui events from getting a turn. You can force your handler onto the thread pool to avoid this.
2) In the old days, any delay less than 200 ms was likely to prevent other events from being handled. Presumably, the scheduler decided that was not enough time to justify the overhead of saving state switching to a new event, and coming back. It may not be the case now, but I still follow the habit of using 200 ms or more. It may not add anything when the handler is not on the gui thread.
3) Your code as written is only an infinite loop if GetForegroundWindow() forever returns null. In such a case, you have a system error or a corrupt program. You should limit the time spent in the loop, and when exceeding that limit, treat it as a severe or non-recoverable error.
Here is a suggested modification that does these things. Note that in your code, the Deactivate event handler did not return until done, while this example puts the work on a thread and returns right away. The thread task will live at most 60 seconds before being returned to the thread pool.
this.Deactivate += new EventHandler((a, b) => ThreadPool.QueueUserWorkItem((obj) =>
{
if (!Monitor.TryEnter(deactivateLockObject))
return;
try
{
int count = 0;
int interval = 200;
while (count < 60000)
{
IntPtr foregroundWindowHandle = CSUTIL.GetForegroundWindow();
if (foregroundWindowHandle.ToString() != "0")
{
uint currentForegroundThreadId = CSUTIL.GetWindowThreadProcessId(foregroundWindowHandle, IntPtr.Zero);
if (new uint[] { threadidW1,threadidW2,threadidW3,etc. }.All((currentThreadId) => { return currentThreadId != currentForegroundThreadId; }))
{
// do the work on the gui thread
this.Invoke(new Action(this.MakeInvisible)); // Executes the closing & cleanup routine
}
return;
}
count += interval;
Thread.Sleep(interval);
}
this.Invoke(new Action(this.HandleSevereError));
}
finally
{
Monitor.Exit(deactivateLockObject);
}
}));
I'm trying to figure out how I can use Console.ReadLine and a timer. My console program is designed to run a long process automatically, with this process restarting every 30 seconds after the previous process completed. I want to give the user the ability to break the auto-run by typing a command though. If I use Console.ReadLine() though, it will wait until the user enters something, whereas I want the program to continue on through a loop if nothing is entered within 30 seconds. . . Any thoughts??
For example:
RunProcess > Wait 30s for User Input. If none: Continue Loop
Thanks a lot!
You could run your timer on a separate thread. When the user enters text, store it in a variable that is accessible to both threads. When the timer ticks, see if anything is entered and continue accordingly.
Be sure to be thread safe :-)
EDIT:
You can use a System.Threading.Timer to tick every 30 seconds and in its callback method, check if the text has been set.
Don't use Console.ReadLine() but check if Console.KeyAvailable is true and then read Console.ReadKey() to check for exit condition.
Try this example code
class Program
{
static bool done;
static void Main(string[] args)
{
int count = 0;
done = false;
while (!done)
{
Thread.Sleep(2000);
count++;
Console.WriteLine("Calculation #" + count.ToString());
if (Console.KeyAvailable)
{
ConsoleKeyInfo key = Console.ReadKey();
if (key.Key == ConsoleKey.Escape)
{
done = true;
}
}
}
Console.WriteLine();
Console.WriteLine("end");
}
}