I have three threads which are supposed to add a random int to a queue, a fourth that dequeues an int, and a fifth that prints the numbers within it. I'm using threads because they will eventually be needed for the scope of this program and to enqueue/dequeue far more numbers, but having issues with generating a random int. I'm using a class RandomGenerator to create the number, and creating an instance of this class then invoking its GetRandom method to set an int field to a random number. I'm then passing this field into the first three threads which invoke the method to enqueue. The int that prints is not random and I realize this is because I'm simply calling the method at the beginning of the program and passing the same exact number to all three threads. I'm relatively new to C# and realize I may be making a basic mistake. I also realize the fourth thread sometimes accesses the queue when it's empty but isn't as important at the moment. I have tried a number of different things with this and could also have the number generator in the Program class. Here is the code:
...
class Program
{
static void Main()
{
Program p = new Program();
RandomGenerator rg = new RandomGenerator();
Queue<int> numberQueue = new Queue<int>();
int randomNumber = rg.GetRandom(1, 10);
Thread T1 = new Thread(delegate () { p.EnqueueNumber(numberQueue, randomNumber); });
Thread T2 = new Thread(delegate () { p.EnqueueNumber(numberQueue, randomNumber); });
Thread T3 = new Thread(delegate () { p.EnqueueNumber(numberQueue, randomNumber); });
Thread T4 = new Thread(delegate () { p.DequeueNumber(numberQueue); });
Thread T5 = new Thread(delegate () { p.PrintNumbers(numberQueue); });
T1.Start();
T2.Start();
T3.Start();
T4.Start();
T5.Start();
T1.Join();
T2.Join();
T3.Join();
T4.Join();
T5.Join();
}
public void EnqueueNumber(Queue<int> numberQueue, int randomNumber)
{
numberQueue.Enqueue(randomNumber);
}
public void DequeueNumber(Queue<int> numberQueue)
{
numberQueue.Dequeue();
}
public void PrintNumbers(Queue<int> numberQueue)
{
foreach (int i in numberQueue)
{
Console.Write(i);
}
Console.ReadKey();
}
}
public class RandomGenerator
{
private static Random _random = new Random();
private static object syncLock = new object();
public int GetRandom(int min, int max)
{
lock (syncLock)
{
return _random.Next(min, max);
}
}
}
...
You are passing the return value of the GetRandom() method of your single RandomGenerator instance to each of the threads.
You need to pass a reference to the RandomGenerator to each of the threads instead, so GetRandom() can be called each time.
Thread T1 = new Thread(delegate () { p.EnqueueNumber(numberQueue, rg); });
If you create a RandomGenerator per thread you can also stop using locks which are overkill for this use case.
Finally if you insist on concurrent multi-write to, single-read from the same queue, you should also look at ConcurrentQueue rather than Queue as it is thread-safe.
Related
I have a recursive algorithm that creates two new threads each time through. My tests crash with the following error when the array's length is 100k. I beleive this is exceeding the thread pool and/or running out of memory.
The question now, is how can I redesign the algorithm to not crash?
Test Authoring and Execution Framework: TE.ProcessHost.Managed[v5.3-1509] has stopped working
public class MyParamObj
{
public int[] MyArray;
public int MyIntOne;
public int MyIntTwo;
public static Create( int[] myArray, int myIntOne, int myIntTwo )
{
return new MyParamObj
{
MyArray = myArray,
MyIntOne = myIntOne,
MyIntTwo = myIntTwo
};
}
}
public class MyClass
{
public void Entry( int[] myArray)
{
int intOne = 0;
int intTwo = myArray.Length;
MyDelegate( MyParamObj.Create( myArray, intOne, intTwo) );
}
private void MyDelegate( object paramaObject )
{
var parameters = paramaObject as MyParamObjCreate;
if (parameters == null) throw new ArgumentNullException(nameof(parameters));
// just sample values
int intOne = 0;
int intTwo = 0;
int intThree = 0;
int intFour = 0
var threadOneParams = MyParamObj.Create( parameters.MyArray, intOne, intTwo );
var threadTwoParams = MyParamObj.Create( parameters.MyArray, intThree, intFour );
var threads = new Thread[2];
threads[0] = new Thread( MyDelegate );
threads[1] = new Thread( MyDelegate );
threads[0].Start(threadOneParams);
threads[1].Start(threadTwoParams);
threads[0].Join();
threads[1].Join();
//reorder elements within the array
}
}
Update 3
I think I am exceeding the thread pool's max limit. When I have an array that's 100k long and I'm recursive down to a size of 1, I'll have 100k+ threads I think. Maximum number of threads in a .NET app? So, I guess my next question, is how do I recursively do this operation while not exceeding the thread limit?
It's hard to tell since you left out huge chunks of code, but it looks like with the line threads[0] = new Thread( MyDelegate ); you have a function that is creating new threads of itself. Your program will explode as it recursively creates threads until it runs out of memory.
I am new in Threads.
And wanted to write a simple program with threads in C#.
The goal was when I press any key it must create new thread,
and every thread must write count which increments it's value every time,
when new thread was created. But result was not what expected :).
It first waits for keypress and after keypress it writes only 111111111111111.... It does not write 2, 3 ,4 and etc. So what is the problem? How can I solve it?
The expected result was like that:
11112222333311112222333344441111...
The code is below.
class Program
{
static Thread t;
static int count = 1;
static void Main(string[] args)
{
Console.Title = "Thread Test";
t = new Thread(wait);
t.Start();
Console.WriteLine("Main Thread End...");
}
static void write(object o)
{
while(true)
{
Console.Write(o.ToString());
Thread.Sleep(500);
}
}
static void wait()
{
Console.ReadKey();
Thread tt = new Thread(write);
tt.Start(count);
count++;
}
}
Perhaps a recursive wait() method is what you want?
static void wait()
{
Console.ReadKey();
Thread tt = new Thread(write);
tt.Start(count);
count++;
wait(); //Added
}
Try this sample :-)
You can try to create more different tasks with different priority.
In the write() method you can printing the name of current task, if you want storage in class more different value you can add property through inheritance
class Program
{
static List<Thread> lst = new List<Thread>();
//static Thread t;
static int count = 1;
static void Main(string[] args)
{
System.Console.Title = "Thread Test";
createThread();
foreach (Thread t in lst) t.Start();
//System.Console.WriteLine("Main Thread End...");
}
static void write()
{
while (true)
{
System.Console.Write(Thread.CurrentThread.Name);
Thread.Sleep(500);
}
}
static void createThread()
{
Random rnd = new Random();
while (count<=5)
{
Thread tt = new Thread(write);
if (rnd.Next(0,10)>=5)
{
tt.Priority = ThreadPriority.Highest;
}
else
{
tt.Priority = ThreadPriority.Lowest;
}
tt.Name = count.ToString();
lst.Add(tt);
count++;
}
}
}
Here's what I'm trying to do:
Get one html page from url which contains multiple links inside
Visit each link
Extract some data from visited link and create object using it
So far All i did is just simple and slow way:
public List<Link> searchLinks(string name)
{
List<Link> foundLinks = new List<Link>();
// getHtmlDocument() just returns HtmlDocument using input url.
HtmlDocument doc = getHtmlDocument(AU_SEARCH_URL + fixSpaces(name));
var link_list = doc.DocumentNode.SelectNodes(#"/html/body/div[#id='parent-container']/div[#id='main-content']/ol[#id='searchresult']/li/h2/a");
foreach (var link in link_list)
{
// TODO Threads
// getObject() creates object using data gathered
foundLinks.Add(getObject(link.InnerText, link.Attributes["href"].Value, getLatestEpisode(link.Attributes["href"].Value)));
}
return foundLinks;
}
To make it faster/efficient I need to implement threads, but I'm not sure how i should approach it, because I can't just randomly start threads, I need to wait for them to finish, thread.Join() kind of solves 'wait for threads to finish' problem, but it becomes not fast anymore i think, because threads will be launched after earlier one is finished.
The simplest way to offload the work to multiple threads would be to use Parallel.ForEach() in place of your current loop. Something like this:
Parallel.ForEach(link_list, link =>
{
foundLinks.Add(getObject(link.InnerText, link.Attributes["href"].Value, getLatestEpisode(link.Attributes["href"].Value)));
});
I'm not sure if there are other threading concerns in your overall code. (Note, for example, that this would no longer guarantee that the data would be added to foundLinks in the same order.) But as long as there's nothing explicitly preventing concurrent work from taking place then this would take advantage of threading over multiple CPU cores to process the work.
Maybe you should use Thread pool :
Example from MSDN :
using System;
using System.Threading;
public class Fibonacci
{
private int _n;
private int _fibOfN;
private ManualResetEvent _doneEvent;
public int N { get { return _n; } }
public int FibOfN { get { return _fibOfN; } }
// Constructor.
public Fibonacci(int n, ManualResetEvent doneEvent)
{
_n = n;
_doneEvent = doneEvent;
}
// Wrapper method for use with thread pool.
public void ThreadPoolCallback(Object threadContext)
{
int threadIndex = (int)threadContext;
Console.WriteLine("thread {0} started...", threadIndex);
_fibOfN = Calculate(_n);
Console.WriteLine("thread {0} result calculated...", threadIndex);
_doneEvent.Set();
}
// Recursive method that calculates the Nth Fibonacci number.
public int Calculate(int n)
{
if (n <= 1)
{
return n;
}
return Calculate(n - 1) + Calculate(n - 2);
}
}
public class ThreadPoolExample
{
static void Main()
{
const int FibonacciCalculations = 10;
// One event is used for each Fibonacci object.
ManualResetEvent[] doneEvents = new ManualResetEvent[FibonacciCalculations];
Fibonacci[] fibArray = new Fibonacci[FibonacciCalculations];
Random r = new Random();
// Configure and start threads using ThreadPool.
Console.WriteLine("launching {0} tasks...", FibonacciCalculations);
for (int i = 0; i < FibonacciCalculations; i++)
{
doneEvents[i] = new ManualResetEvent(false);
Fibonacci f = new Fibonacci(r.Next(20, 40), doneEvents[i]);
fibArray[i] = f;
ThreadPool.QueueUserWorkItem(f.ThreadPoolCallback, i);
}
// Wait for all threads in pool to calculate.
WaitHandle.WaitAll(doneEvents);
Console.WriteLine("All calculations are complete.");
// Display the results.
for (int i= 0; i<FibonacciCalculations; i++)
{
Fibonacci f = fibArray[i];
Console.WriteLine("Fibonacci({0}) = {1}", f.N, f.FibOfN);
}
}
}
This question already has an answer here:
Thread alters passed Int, if start() is called separately
(1 answer)
Closed 7 years ago.
I have no idea what is going on in this. I'm trying to test thread safety of a class by spawning 100 threads to access it constantly, but it seems my anonymous method parameters are changing themselves to values they should never be and I'm confused as to why. As I have no idea what's going on, I'll just post all the functions involved in testing. Somehow I'm ending up with "Thread 98" getting the parameter "num = 100"... That shouldn't be possible and I have no idea what kind of hokey pokey is going on that is changing the integer. (in method "ThreadWriting(int num)" you'll see the point where I check for "num" to equal 100, where I put a break point to catch the offending thread in the act, and it breaks every time. Otherwise it throws an "IndexOutofRangeException" on the array "counts". I'm just trying to see if my threads are generally getting equal access to the class they're all trying to use at once.
public delegate void TempDel();
public TempDel InvokeTest;
public void TRTest3(Form1 sender)
{
InvokeTest = new TempDel(UpdateInvoke);
Thread t = new Thread(() => ConsoleUpdateTest(sender));
t.IsBackground = true;
t.Start();
POConsole.Instance.MaxLines = 20;
for(int i = 0; i < 100; i++)
{
Thread t2 = new Thread(() => ThreadWriting(i));
t2.IsBackground = true;
t2.Name = String.Format("Thread {0}", i);
t2.Start();
}
}
public ulong[] counts = new ulong[100];
public void ThreadWriting(int num)
{
if(num == 100)
{
bool stop = true;
}
while (true)
{
POConsole.Instance.WriteLine("Hello from Thread " + num);
counts[num]++;
}
}
public void ConsoleUpdateTest(Form1 sender)
{
while(true)
{
sender.Invoke(InvokeTest);
Thread.Sleep(5);
}
}
public void UpdateInvoke()
{
QuickTestBox.Text = POConsole.Instance.FullFeed;
}
All my threads are named, as you can see, and none of them receives the name "Thread 100" so I have no idea how one of the other threads could get passed a parameter of 100 or the parameter could be corrupted in some way.
Apparently my thread-safety checking isn't thread safe in some way?
This is a simple closure issue, you should not be using the for loop counter as a threading parameter issue, issue happens out here, for loop and thread execution do not run at same speed, so value of i can change for multiple threads:
for(int i = 0; i < 100; i++)
{
Thread t2 = new Thread(() => ThreadWriting(i));
t2.IsBackground = true;
t2.Name = String.Format("Thread {0}", i);
t2.Start();
}
Use following modification, create a local variable from loop counter
for(int i = 0; i < 100; i++)
{
int j = i;
Thread t2 = new Thread(() => ThreadWriting(j));
t2.IsBackground = true;
t2.Name = String.Format("Thread {0}", j);
t2.Start();
}
I have following code which throws SemaphoreFullException, I don't understand why ?
If I change _semaphore = new SemaphoreSlim(0, 2) to
_semaphore = new SemaphoreSlim(0, int.MaxValue)
then all works fine.
Can anyone please find fault with this code and explain to me.
class BlockingQueue<T>
{
private Queue<T> _queue = new Queue<T>();
private SemaphoreSlim _semaphore = new SemaphoreSlim(0, 2);
public void Enqueue(T data)
{
if (data == null) throw new ArgumentNullException("data");
lock (_queue)
{
_queue.Enqueue(data);
}
_semaphore.Release();
}
public T Dequeue()
{
_semaphore.Wait();
lock (_queue)
{
return _queue.Dequeue();
}
}
}
public class Test
{
private static BlockingQueue<string> _bq = new BlockingQueue<string>();
public static void Main()
{
for (int i = 0; i < 100; i++)
{
_bq.Enqueue("item-" + i);
}
for (int i = 0; i < 5; i++)
{
Thread t = new Thread(Produce);
t.Start();
}
for (int i = 0; i < 100; i++)
{
Thread t = new Thread(Consume);
t.Start();
}
Console.ReadLine();
}
private static Random _random = new Random();
private static void Produce()
{
while (true)
{
_bq.Enqueue("item-" + _random.Next());
Thread.Sleep(2000);
}
}
private static void Consume()
{
while (true)
{
Console.WriteLine("Consumed-" + _bq.Dequeue());
Thread.Sleep(1000);
}
}
}
If you want to use the semaphore to control the number of concurrent threads, you're using it wrong. You should acquire the semaphore when you dequeue an item, and release the semaphore when the thread is done processing that item.
What you have right now is a system that allows only two items to be in the queue at any one time. Initially, your semaphore has a count of 2. Each time you enqueue an item, the count is reduced. After two items, the count is 0 and if you try to release again you're going to get a semaphore full exception.
If you really want to do this with a semaphore, you need to remove the Release call from the Enqueue method. And add a Release method to the BlockingQueue class. You then would write:
private static void Consume()
{
while (true)
{
Console.WriteLine("Consumed-" + _bq.Dequeue());
Thread.Sleep(1000);
bq.Release();
}
}
That would make your code work, but it's not a very good solution. A much better solution would be to use BlockingCollection<T> and two persistent consumers. Something like:
private BlockingCollection<int> bq = new BlockingCollection<int>();
void Test()
{
// create two consumers
var c1 = new Thread(Consume);
var c2 = new Thread(Consume);
c1.Start();
c2.Start();
// produce
for (var i = 0; i < 100; ++i)
{
bq.Add(i);
}
bq.CompleteAdding();
c1.Join();
c2.Join();
}
void Consume()
{
foreach (var i in bq.GetConsumingEnumerable())
{
Console.WriteLine("Consumed-" + i);
Thread.Sleep(1000);
}
}
That gives you two persistent threads consuming the items. The benefit is that you avoid the cost of spinning up a new thread (or having the RTL assign a pool thread) for each item. Instead, the threads do non-busy waits on the queue. You also don't have to worry about explicit locking, etc. The code is simpler, more robust, and much less likely to contain a bug.