c# Thread unactivity property - c#

I have a function that reads numbers from console and writes them to queue and a massive of threads that should read numbers from queue, calculate factorials and write it to file.
static void Main(string[] args)
{
int threadsNumber = 0;
Console.WriteLine("Enter the number of threads: ");
while ((Int32.TryParse(Console.ReadLine(), out threadsNumber) == false)||(threadsNumber <= 0))
{
Console.WriteLine("You need to enter a positive number!");
}
Console.Clear();
Queue<int> numbersQueue = new Queue<int>();
Thread [] threadMas = new Thread[threadsNumber];
for (int i = 0; i < threadsNumber; i++)
{
threadMas[i] = new Thread(() => ThreadProc.ThreadProcStart(numbersQueue));
threadMas[i].Start();
}
//some code...
ThreadProc:
class ThreadProc
{
private static object locker = new object();
public static void ThreadProcStart(Queue<int> queue)
{
while (true)
{
int num = Deq(queue); //Checks if queue is empty. If not -
//Returns first element
if (num != -1)
{
BigInteger bigInt = Factorial.FactTree(num); //factorical
Writer.WriteToFile(num + " factorial: " + bigInt, "result.txt"); //write to file
}
else
{
// Here I need to add something
Thread.Sleep(0);
}
}
}
public static int Deq(Queue<int> queue)
{
lock (locker)
{
if (queue.Count != 0)
{
return queue.Dequeue();
}
return -1;
}
}
}
I need to stop all threads when all calculations are done. How can i mark thread as "unactive" when the queue is empty without actually aborting it?

Use BlockingCollection, which underneath the covers uses ConcurrentQueue. Your code will be soooo much simpler and you won't have to worry about subtle locking bugs.
Your code would then look something like this:
static void Main(string[] args)
{
int threadsNumber = 0;
Console.WriteLine("Enter the number of threads: ");
while ((Int32.TryParse(Console.ReadLine(), out threadsNumber) == false) || (threadsNumber <= 0))
{
Console.WriteLine("You need to enter a positive number!");
}
Console.Clear();
BlockingCollection<int> queue = new BlockingCollection<int>();
Thread[] threadMas = new Thread[threadsNumber];
for (int i = 0; i < threadsNumber; i++)
{
threadMas[i] = new Thread(ProcessQueue);
threadMas[i].Start(queue);
}
string userInput = null;
do
{
Console.WriteLine("Enter a number: ");
userInput = Console.ReadLine();
if (userInput != "stop") {
queue.Add(int.Parse(userInput)); // These numbers get process by the threads in parallel.
}
} while (userInput != "stop");
queue.CompleteAdding(); // Use this to signal that no more items will be added to the queue.
// Now the main thread exits.
// But the program stays alive until the other threads finish
// clearing the queue.
}
private static void ProcessQueue(object data)
{
BlockingCollection<int> queue = (BlockingCollection<int>)data;
foreach (var num in queue.GetConsumingEnumerable()) // This will automatically exit the loop once CompleteAdding is called and the queue is empty.
{
BigInteger bigInt = Factorial.FactTree(num); //factorical
Writer.WriteToFile(num + " factorial: " + bigInt, "result.txt"); //write to file
}
}

Related

How to read button mashing in c#

I've been trying to get a button mashing minigame working in my RPG, but I haven't managed to get it to work. This is the code I've created:
using System;
namespace CounterAttack
{
class Program
{
public static int n = 0;
public static int buttonmash = 0;
public static string buttonpressed;
public static void CounterAttack()
{
n = 0;
while (n < 4000)
{
buttonpressed = Console.ReadKey().ToString();
System.Threading.Thread.Sleep(1);
n = n + 1;
if (buttonpressed == " ")
{
buttonmash = buttonmash + 1;
buttonpressed = "a";
}
else
{
buttonpressed = "a";
}
}
Console.WriteLine($"You pressed spacebar {buttonmash} times ");
}
static void Main(string[] args)
{
CounterAttack();
System.Threading.Thread.Sleep(1000);
Console.ReadKey();
}
}
}
For reasons unknown to me, the program will not exit the while loop. This means I can't check if the other parts of code will work at all.
So my question is: How can I alter this code to read the amount of times spacebar has been pressed in 4 seconds?
This sort-of works, so long as you press the space bar after the 4 second timer is up.
static void Main(string[] args)
{
var startTime = DateTime.Now;
var n = 0;
while (DateTime.Now < startTime.AddSeconds(4))
{
var key = Console.ReadKey();
System.Threading.Thread.Sleep(1);
if (key.Key == ConsoleKey.Spacebar) n = n + 1;
}
Console.WriteLine($"You pressed spacebar {n} times ");
}
"I've been trying to get a button mashing minigame working in my RPG, but I haven't managed to get it to work."
You are doing this in a console application. So the answer is on a spectrum from "not easily" to "plain impossible". I hope somebody else can give you answer with more precision along that axis.
Game development and the GUI technologies do not mix that well to begin with. That old Solitaire game was pretty much the upper limit of what games you can do in them. Console matches it even less then that.
All the serious game development is done in any enviroment that comes with a game loop. XNA is a bit dated, but for .NET Core there is some options: https://www.microsoft.com/net/apps/gaming
Try this :
class Program
{
private static int numSpaces = 0;
static void Main(string[] args)
{
Thread th = new Thread(CheckSpace);
th.Start();
th.Join();
Console.WriteLine($"You pressed space {numSpaces} times");
Console.Read();
}
private static void CheckSpace()
{
Stopwatch sw = new Stopwatch();
sw.Start();
while (true)
{
if (Console.KeyAvailable)
{
if (Console.ReadKey().Key == ConsoleKey.Spacebar)
{
numSpaces++;
}
}
if (sw.ElapsedMilliseconds>= 4000)
{
break;
}
Thread.Sleep(10);
}
}
}
#auberg's solution is good, but you really don't need a second thread. Yeah, calling Thread.Sleep() on the main thread is a bad idea, but doing it for such a short time is un-noticeable anyway.
Try this:
public static void CountKeyPresses()
{
Console.WriteLine("OK, start pressing the space bar");
var numPresses = 0;
var stopWatch = new Stopwatch();
stopWatch.Start();
while (stopWatch.ElapsedMilliseconds < 4000)
{
if (Console.KeyAvailable && Console.ReadKey().Key == ConsoleKey.Spacebar)
{
++numPresses;
}
System.Threading.Thread.Sleep(10);
}
Console.WriteLine($"\r\nYou pressed the spacebar {numPresses} times");
}

Use multithreading to count?

I am just starting to use multi-threading, and I am trying to build a console application that starts to count with 2 different threads when the user hits the Enter key, and stops counting when the Enter key is pressed a second time, and then outputs the count for both threads (I realize that with my code, these will be 2 different numbers). I set this up, but for some reason, one of the numbers is usually negative.There is also quite a bit of a delay before I receive count output. Why am I getting negative counts, why is the delay so long, and how can I correct this?
My code so far;
class Program
{
static void Main(string[] args)
{
System.Threading.Thread threadA = new Thread(ThreadA);
System.Threading.Thread threadB = new Thread(ThreadB);
Console.WriteLine("Once you press enter, this application will count as high as it can until you press enter again.");
ConsoleKeyInfo info = Console.ReadKey();
if (info.Key == ConsoleKey.Enter)
{
threadA.Start();
threadB.Start();
}
}
private static bool continueCounting = true;
static void ThreadA()
{
int count = 0;
for (int i = 0; i < int.MaxValue ; i++)
{
count++;
}
ConsoleKeyInfo info2 = Console.ReadKey();
if (info2.Key == ConsoleKey.Enter)
continueCounting = false;
Console.WriteLine(count);
}
static void ThreadB()
{
int count = 0;
while (continueCounting)
{
count++;
}
Console.WriteLine(count);
Console.ReadLine();
}
}
one of the numbers is usually negative
That's because there was no limit guard on the ThreadB loop. It was entirely possible for count to reach MaxValue then wrap around to negative maxvalue.
I also put all keyboard checks in your main thread where they arguably should be. It is here that we set continueCounting to false when the second enter key is pressed.
I also made continueCounting volatile as it is being used by multiple threads and its value should not be CPU optimised/cached.
Try this code, this fixes the delay you were experiencing; allows both threads to count at once; and exit ASAP when the enter key is pressed.
class Program
{
#region Static fields
private static volatile bool continueCounting = true;
#endregion
#region Methods
static void Main(string[] args)
{
var threadA = new Thread(ThreadA);
var threadB = new Thread(ThreadB);
Console.WriteLine(
"Once you press enter, this application will count as high as it can until you press enter again.");
var info = Console.ReadKey();
if (info.Key == ConsoleKey.Enter)
{
threadA.Start();
threadB.Start();
}
info = Console.ReadKey();
if (info.Key == ConsoleKey.Enter)
{
continueCounting = false;
}
Console.ReadLine();
}
static void ThreadA()
{
var count = 0;
for (var i = 0; i < int.MaxValue && continueCounting; i++)
{
count++;
}
Console.WriteLine($"A: {count}");
}
static void ThreadB()
{
var count = 0;
while (continueCounting && count < int.MaxValue)
{
count++;
}
Console.WriteLine($"B: {count}");
}
#endregion
}

Synchronization with semaphore

I try to synchronize three threads (named "1", "2" and "3") using Semaphore class. They have to print a string into console respecting consequence: 1->2->3. Here is my code:
class MyThread
{
public Thread Thrd;
static Semaphore sem = new Semaphore(1, 1);
static int flag = 1;
public MyThread(string name)
{
Thrd = new Thread(this.Run);
Thrd.Name = name;
Thrd.Start();
}
void Run()
{
sem.WaitOne();
if (Convert.ToInt32(Thrd.Name) == flag)
{
Console.WriteLine("Thread " + Thrd.Name);
flag++;
}
if (flag == 4)
flag = 1;
Thread.Sleep(300);
sem.Release();
}
}
class SemaphoreDemo
{
static void Main()
{
for (int i = 0; i < 10; i++)
{
MyThread mt1 = new MyThread("1");
MyThread mt2 = new MyThread("2");
MyThread mt3 = new MyThread("3");
mt1.Thrd.Join();
mt2.Thrd.Join();
mt3.Thrd.Join();
}
}
}
But sometimes strings from threads #2 and #3 are not seen. Where is my mistake and how can I fix this problem?
Thank you very much!
The problem is that sometimes a thread will acquire the semaphore out of order, and you don't have any retry logic. Take a look at your Run method.
void Run()
{
sem.WaitOne();
if (Convert.ToInt32(Thrd.Name) == flag)
{
Console.WriteLine("Thread " + Thrd.Name);
flag++;
}
if (flag == 4)
flag = 1;
Thread.Sleep(300);
sem.Release();
}
Now, what happens if the thread named "3" acquires the semaphore first? flag is equal to 1, so the conditional code won't be executed. The thread will just sleep for 300 milliseconds and then exit. If you want this to work, you have to make the thread retry:
void Run()
{
bool success = false;
while (!success)
{
sem.WaitOne();
if (Convert.ToInt32(Thrd.Name) == flag)
{
Console.WriteLine("Thread " + Thrd.Name);
flag++;
success = true;
}
sem.Release();
if (!success)
{
// let somebody else try
Thread.Sleep(300);
}
}
}
That will make your sample work as expected.
I suspect that this is just an exercise to see how threading and semaphores work. Note, however, that a Mutex is usually more appropriate than a Semaphore with a maximum count of 1.
Note also that there are other ways to make threads execute in sequence, although truthfully if you're going to sequence your threads then you probably don't need more than one thread. Unless those threads are doing other things and they only need to sequence once--or infrequently.

How can we run two threads paralleling?

public class Program
{
static void Main(string[] args)
{
var myThread = new TestThread();
Thread t = new Thread(new ThreadStart(myThread.PrintName));
Thread t1 = new Thread(new ThreadStart(myThread.PrintType));
t.Start();
t1.Start();
Console.Read();
}
}
public class TestThread
{
public void PrintName()
{
for (int i = 1; i <= 50; i++)
{
Console.WriteLine("Name {0}", i);
}
}
public void PrintType()
{
for (int i = 100; i <= 180; i++)
{
Console.WriteLine("Type {0}", i);
}
}
}
Here How can i fixed it show that i can generate output in sequential i.e
first output of Name then only output of Type... Also I want to know about using Lock() in threads? where can i get good example. I am beginners in threading and need v.simple example.
Try this:
var myThread = new TestThread();
var x=Task.Factory.StartNew(() => myThread.PrintName());
x.ContinueWith(p => PrintType());
x.Wait();
You can look at this
There are multiple other articles, just google for 'introduction threading c#'.
The purpose of threads is to allow things to happen at the same time. If you want things to happen one after another (i.e. sequentially), then do not use threads:
var obj = new TestThread();
obj.PrintName();
obj.PrintType();
Console.Read();
Or put PrintName and PrintType into the same thread, in order to keep the UI responsive:
var myThread = new TestThread();
Thread t = new Thread(new ThreadStart(
() => {
myThread.PrintName(); myThread.PrintType();
}
));
t.Start();
// Do things in the UI meanwhile
for (i = 0; i < 100; i++) {
Console.WriteLine("UI thread {0}", i);
}
Console.Read();
//This will run two operation in sequence.
public class TestThread
{
public object obj = new object();
public void PrintName()
{
Monitor.Enter(obj);
for (int i = 1; i <= 50; i++)
{
Console.WriteLine("Name {0}", i);
}
Monitor.Exit(obj);
}
public void PrintType()
{
Monitor.Enter(obj);
for (int i = 100; i <= 180; i++)
{
Console.WriteLine("Type {0}", i);
}
Monitor.Exit(obj);
}
}
That will do the trick, you should read carefully and try to do it with 3 loops by yourself:
private static void SimpleLockTest()
{
Task[] myTasks = new Task[2];
myTasks[0] = Task.Factory.StartNew(() =>
{
LockTestThreadOne();
});
myTasks[1] = Task.Factory.StartNew(() =>
{
LockTestThreadTwo();
});
Task.WaitAll(myTasks);
Console.WriteLine("Done, press ENTER to quit");
Console.ReadLine();
}
private static object locker = new object();
private static void LockTestThreadOne()
{
Monitor.Enter(locker);
for (int i = 1; i <= 50; i++)
{
Console.WriteLine("Name {0}", i);
Monitor.Pulse(locker);
Monitor.Wait(locker);
}
Monitor.Exit(locker);
}
private static void LockTestThreadTwo()
{
Monitor.Enter(locker);
for (int i = 100; i <= 180; i++)
{
Console.WriteLine("Type {0}", i);
Monitor.Pulse(locker);
Monitor.Wait(locker, 10);
}
Monitor.Exit(locker);
}

Why this consumer-producer thread is frozen?

I've made this producer-consumer sample, but I don't know why it freezes at the end.
Where is the problem? If I put a breakpoint at line setNum(-99); and then after break continue it finishes OK.
Please also tell me if this code is ok and threadsafe. It must work like that, so meanwhile consumer is processing its given value, all other values from producer must be ignored.
I am very new to multithreading.
class Program
{
delegate void SetNumberDelegate(int number);
static void Main(string[] args)
{
Random rnd = new Random();
ConsumerClass consumerClass = new ConsumerClass();
SetNumberDelegate setNum = new SetNumberDelegate(consumerClass.setNumber);
Thread.Sleep(20);
int num;
int count = 0;
Console.WriteLine("Start");
while (count++ < 100)
{
num = rnd.Next(0, 100);
Console.WriteLine("Generated number {0}", num);
if (num > 30)
{
setNum(num);
}
}
setNum(-99);
Console.WriteLine("End");
Console.ReadKey();
}
}
class ConsumerClass : IDisposable
{
private int number;
private object locker = new object();
private EventWaitHandle _wh = new AutoResetEvent(false);
private Thread _consumerThread;
public ConsumerClass()
{
number = -1;
_consumerThread = new Thread(consumeNumbers);
_consumerThread.Start();
}
public void Dispose()
{
setNumber(-99);
_consumerThread.Join();
_wh.Close();
}
public void setNumber(int num)
{
if (Monitor.TryEnter(locker))
{
try
{
number = num;
Console.WriteLine("Setting number {0}", number);
}
finally
{
// Ensure that the lock is released.
Monitor.Exit(locker);
}
_wh.Set();
}
}
public void consumeNumbers()
{
while (true)
{
Monitor.Enter(locker);
if (number > -1)
{
try
{
Console.WriteLine("Processing number:{0}", number);
// simulate some work with number e.g. computing and storing to db
Thread.Sleep(20);
Console.WriteLine("Done");
number = -1;
}
finally
{
Monitor.Exit(locker);
}
}
else
{
if (number == -99)
{
Console.WriteLine("Consumer thread exit");
return;
}
Monitor.Exit(locker);
_wh.WaitOne(); // No more tasks - wait for a signal
}
}
}
}
Rewrite setNumber like this to see your problem:
public void setNumber(int num) {
if (Monitor.TryEnter(locker)) {
// etc..
}
else Console.WriteLine("Number {0} will never make it to the consumer", num);
}
You'll have to block, waiting for the consumer to be ready to consume or use a queue.
Monitor.TryEnter(locker); will usually fail (including for -99) so you aren't going to set a fair number of the values, which is why the output is lacking in setting statements. This is because it will not wait to acquire the lock it will just return false.
The problem appears to be in the last part of the code. You're holding the lock when you execute this:
else
{
if (number == -99)
{
Console.WriteLine("Consumer thread exit");
return;
}
Monitor.Exit(locker);
_wh.WaitOne(); // No more tasks - wait for a signal
}
So if number == 99, the method returns without releasing the lock.
Your ConsumeNumbers method is overly complex. You can simplify it:
while (true)
{
_wh.WaitOne();
lock (locker)
{
if (number == -99)
break;
if (number > -1)
{
// process the number.
number = -1;
}
}
}
That will do the same thing, and is much simpler code.
By the way, the construct:
lock (locker)
{
// do stuff here
}
is the same as:
Monitor.Enter(locker);
try
{
// do stuff here
}
finally
{
Monitor.Exit(locker);
}

Categories

Resources