Using Random in multiple threads sharing same method - c#

I'm using to following xaml to create a simple racer app
<StackPanel>
<Slider x:Name="racerOne" Maximum="1000"/>
<Slider x:Name="racerTwo" Maximum="1000"/>
<Button Content="Start Race" Click="myButton_Click"/>
</StackPanel>
I use the following code
private void myButton_Click(object sender, RoutedEventArgs e)
{
Task firstRacer = Task.Run(() => Race(racerOne));
Task secondRacer = Task.Run(() => Race(racerTwo));
}
private void Race(Slider racer)
{
int step = 0;
while (step < 1000)
{
step += new Random().Next(0, 10);
Dispatcher.BeginInvoke(new ThreadStart(() => racer.Value = step));
Thread.Sleep(new Random().Next(0, 300));
}
}
Most of the times (let's say 90% precent) both sliders appear to move together, while in debug I can see each thread generates different values for step. How come?

Random is seeded by the clock; you might want to do something like:
Random rand1 = new Random();
Random rand2 = new Random(rand1.Next());
Task firstRacer = Task.Run(() => Race(racerOne, rand1));
Task secondRacer = Task.Run(() => Race(racerTwo, rand2));
private void Race(Slider racer, Random rand)
{
int step = 0;
while (step < 1000)
{
step += rand.Next(0, 10);
Dispatcher.BeginInvoke(new ThreadStart(() => racer.Value = step));
Thread.Sleep(rand.Next(0, 300));
}
}
This creates two separate Random instances with different seeds (by using the 1st to seed the second), and then passes these into the Race as arguments. This removes any risk of overly-predictable behaviour due to timing.

You should initialize your random generator outside of the loop.
var rand = new Random();
while (step < 1000)
{
step += rand.Next(0, 10);
Dispatcher.BeginInvoke(new ThreadStart(() => racer.Value = step));
Thread.Sleep(rand.Next(0, 300));
}
For more details please go through this Jon Skeet's article:
https://msmvps.com/blogs/jon_skeet/archive/2009/11/04/revisiting-randomness.aspx
Almost every Stack Overflow question which includes the words "random"
and "repeated" has the same basic answer. It's one of the most common
"gotchas" in .NET, Java, and no doubt other platforms: creating a new
random number generator without specifying a seed will depend on the
current instant of time. The current time as measured by the computer
doesn't change very often compared with how often you can create and
use a random number generator – so code which repeatedly creates a new
instance of Random and uses it once will end up showing a lot of
repetition.

When you create a new Random object, it seeds it from the system clock. This has a resolution of only a few milliseconds, so if you create a new Random object more frequently than that, it will produce the same random sequence as the previous one.
The solution is to create only ONE random object (and use a lock to serialise access to it if more than one thread is accessing it at once).

Related

How do I change the background image of a Windows phone app

I am developing an WP8 app and would like to change the background image with several images ; setting time as a variable and showing images in C#,
You can use DispatcherTimer class in order to change the images with respect to time.
Let me suggest you the easiest way. Name your images as numbers like
1.jpg,2.jpg,3.jpg etc and put them inside a folder.
Now you can use either random number class to pick the images in random order or can use the following method to get the sequentially:
DispatcherTimer picture_timer = new DispatcherTimer();
Random rnd = new Random();
picture_timer .Interval = new TimeSpan(0, 0, 3);
picture_timer .Tick += timer_Tick;
picture_timer .Start();
void timer_Tick(object sender, object e)
{
int num = rnd.Next(1, 13); // creates a number between 1 and 12
string image_source = "/Assets/"+num+".jpg";
}

How do i use thread locks in an infinite loop?

I am fairly new to threading in general and i want to try it in C#. I am trying to make a basic simulation of tonnage of something which is decaying every 20 seconds and being refilled every 10 seconds. From what i read, thread safety is something i need to consider as there are two threads; one for decaying the variable tonnage by 160, one for adding a random amount to the tonnage and since they are making transactions to the variable tonnage, i should make sure they are accessed correctly.
I read on how to use lock(object) and i understand the concept for simple thread examples but how do i use it for 2 threads running forever and have to make timely adjustments in the tonnage?
Here is what i have, but when i lock the whole loop, the other thread never spawns. Or do i have the wrong code structure?
public double tonnage = 1000;
private object x = new object();
//Starts the simulation, runs forever until user ends the simulation
private void btnStart_Click(object sender, EventArgs e)
{
//Decay Tonnage
Thread decayTonnageThread = new Thread(() => decayTonnage (tonnage));
decayTonnageThread .Start();
//Add Tonnage
Thread addTonnageThread = new Thread(() => addTonnage (tonnage));
addTonnageThread .Start();
}
//I want to decay the tonnage every 20 seconds
public void decayTonnage (double tonnage)
{
lock(x)
{
while (true)
{
tonnage = tonnage - 160;
Thread.Sleep(20000);
}
}
}
//Add to the tonnage every 10 seconds
public void addTonnage (double tonnage)
{
lock(x)
{
while (true)
{
Random random = new Random();
double randomNumber = random.Next(97, 102);
tonnage = tonnage + randomNumber;
Thread.Sleep(10000);
}
}
}
You want the lock to be as small as possible, only have it around the lines that are interacting with shared objects, not the entire loop. Also, putting Random random = new Random(); in the while loop is a bad habit to have, you should make only one random instance and initialize it outside of the loop.
//I want to decay the tonnage every 20 seconds
public void decayTonnage (double tonnage)
{
while (true)
{
lock(x)
{
tonnage = tonnage - 160;
}
Thread.Sleep(20000);
}
}
//Add to the tonnage every 10 seconds
public void addTonnage (double tonnage)
{
Random random = new Random();
while (true)
{
double randomNumber = random.Next(97, 102);
lock(x)
{
tonnage = tonnage + randomNumber;
}
Thread.Sleep(10000);
}
}
Also, I assume you are doing this for some kind of assignment and must use threads, but if I was doing this for real I would not use threads with loops + a Sleep at all and instead use two timers, one that fired every 20 seconds and one that fired every 10 seconds. Depending on the type of timer you use you may or may-not still need to use a lock.

Parallel functions return different results in C#

I have these codes in my windows form C# application:
private void button7_Click(object sender, EventArgs e)
{
ThreadStart starter = delegate { thread_func(2, 1000000); };
thread1_thread = new Thread(starter);
starter = delegate { thread_func(1000000, 2000000); };
thread2_thread = new Thread(starter);
starter = delegate { thread_func(2000000, 3000000); };
thread3_thread = new Thread(starter);
starter = delegate { thread_func(3000000, 4000000); };
thread4_thread = new Thread(starter);
thread1_thread.Start();
thread2_thread.Start();
thread3_thread.Start();
thread4_thread.Start();
}
void thread_func(decimal input1,decimal input2)
{
for (; input1 < input2; input1++)
{
threadNumbers_list.Add(input1);
if (input1 % 2 != 0)
{
if (isPrime_func(input1))
{
PrimeNumbers_decimal_list.Add(input1);
}
}
}
}
public static Boolean isPrime_func(decimal number)
{
decimal boundary = (decimal)Math.Floor(Math.Sqrt((double)number));
if (number == 1) return false;
if (number == 2) return true;
for (decimal i = 2; i <= boundary; ++i)
{
if (number % i == 0) return false;
}
return true;
}
Every time I run click that button I get different results. I have tried many things but could not figure out why this happens. Even for lower ranges it happens. Just in range of 100 numbers for example it gives the same result always.
Some time my list count reaches 283138 and sometimes 283131 and other near numbers.
Another weird this is that when I comment checking even numbers, operation takes shorter time than this mode. What's wrong?
When multiple threads access a list, that list have to be thread safe or otherwise you are going to have a lot of problems.
.NET provides some thread-safe collections like the ConcurrentQueue<T> class.
Side note: Please consider using Tasks instead of threads. Also, the .NET framework supports data parallelism via the Parallel class. Consider using such class instead.
Regarding the performance when you don't check if the number is even, I tested this locally and I got the following numbers:
It takes ~76 seconds when I don't check if the number is even.
It takes ~66 seconds when I do check if the number is even.
So this does not match your measurements. It might be caused by the way you measure. I measure with a Stopwatch like this:
//...
Stopwatch sw = Stopwatch.StartNew();
thread1_thread.Start();
thread2_thread.Start();
thread3_thread.Start();
thread4_thread.Start();
thread1_thread.Join();
thread2_thread.Join();
thread3_thread.Join();
thread4_thread.Join();
long result = sw.ElapsedMilliseconds;
//...
By the way, here is something that you can do that might save some execution time for you:
Create a normal List<T> instance for each thread inside the thread_func method so that you don't have multi-threading issues. Then after the loop finishes, you can update the master list from the local list. Only updating the master list has to be thread safe. In this case I would prefer that the master list is a normal List<T> and that you use the lock keyword to synchronize access to it because you only need to update it 4 times (the number of threads).

ObservableCollection updating from one method but not another

I have a method that updates my observableCollection
public void UpdateBeat()
{
SequenceCollection = new ObservableCollection<Sequence>();
Random random = new Random();
int randomNumber = random.Next(0, 100);
SequenceCollection.Add(new Sequence(1, 2));
}
I have 2 different methods fired from events - the view updates from 1 of the methods but not the other.
//Does not work
private void BsOnUpdateStep(object sender, EventArgs eventArgs)
{
Console.WriteLine("BS Update");
UpdateBeat();
}
//Works
void total_AudioAvailable(object sender, AsioAudioAvailableEventArgs e)
{
Console.WriteLine("ASIO Written");
UpdateBeat();
}
I have no idea what the difference could be here. The only thing I can tell is that the 1st method fires more often than the 2nd. I cannot get the 2nd to work at all.
I suppose your calls to UpdateBeat are from different threads but ObservableCollection is not thread safe, that is why -probably- you have such strange results.
You should look for an concurrent ObservableCollection.
One such implementation can be found here: http://www.codeproject.com/Tips/414407/Thread-Safe-Improvement-for-ObservableCollection
Try this:
private SequenceCollection = new ObservableCollection<Sequence>();
Random random = new Random();
public void UpdateBeat()
{
int randomNumber = random.Next(0, 100);
SequenceCollection.Add(new Sequence(1, 2));
}
I put the Random instantiation outside of the method too as you should only instantiate this once to get a proper stream of random numbers.

How to make Dynamic TextBox in C#

I have simple FormApplication script that contains button and some TextBoxs.
I want when click on button, one textbox shows some numbers.
How I can make that dynamic.
private void button1_Click(object sender, EventArgs e)
{
txt3.Text = "";
for (int i = 0; i <50; i++)
{
Random random = new Random();
int randomNumber = random.Next(100, 150);
txt3.Text = randomNumber.ToString();
}
}
Now it waits to loop finished and shows latest number.
I want it shows each number during loop in TextBox seperatly.
Seems using Dynamic TextBox is a bit hard, is there any other solution to show this numbers in main form?
Regards,
you need to do it in separate thread and sleep between each iteration or use a timer.
for example:
private int counter;
Timer t = new Timer();
Random random = new Random();
private void button1_Click(object sender, EventArgs e)
{
t.Interval = 100;
t.Tick += new EventHandler(t_Tick);
counter = 0;
t.Enabled = true;
txt3.Text = "";
}
void t_Tick(object sender, EventArgs e)
{
counter++;
int randomNumber = random.Next(100, 150);
txt3.Text = randomNumber.ToString();
if (counter >= 50)
{
t.Enabled = false;
}
}
remember this is just one example out of million ways to do it. a lot of them are good
another way will be using threads:
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(randomize));
t.Start();
}
private void randomize()
{
Random random = new Random();
txt3.Text = "";
for (int i = 0; i < 50; i++)
{
int randomNumber = random.Next(100, 150);
Invoke(new setTxtHandler(setText), randomNumber.ToString());
Thread.Sleep(100);
}
}
private void setText(string val)
{
txt3.Text = val;
}
private delegate void setTxtHandler(string val);
You have to put the Random outside of the loop since it is seeded with the current time and the loop executes too fast.
Random random = new Random();
for (int i = 0; i <50; i++)
{
int randomNumber = random.Next(100, 150);
txt3.Text = randomNumber.ToString();
}
MSDN
The random number generation starts from a seed value. If the same
seed is used repeatedly, the same series of numbers is generated. One
way to produce different sequences is to make the seed value
time-dependent, thereby producing a different series with each new
instance of Random. By default, the parameterless constructor of the
Random class uses the system clock to generate its seed value, while
its parameterized constructor can take an Int32 value based on the
number of ticks in the current time. However, because the clock has
finite resolution, using the parameterless constructor to create
different Random objects in close succession creates random number
generators that produce identical sequences of random numbers.
However, since the loop executes very fast you won't see each value anyway, only the last.
Now it waits to loop finished and shows latest number.
That's because the operation is single-threaded so there's no UI update until it's completed. How you would change that depends on whether this is a Windows application or a Web application.
If this is, for example, a Windows Forms application then you want to call Application.DoEvents() to update the UI each time the loop iterates:
txt3.Text = randomNumber.ToString();
Application.DoEvents();
This will update the UI's text box each time. (Though it will be very fast, so I doubt you'll even notice it. You might throw in a Thread.Sleep() if you want to slow it down.)
If this is a web application, then you'll want to do this whole thing client-side instead of server-side. This is because "updating the UI" in a web application, at least from the server's perspective, means returning the response and waiting for another request. This would result in a lot of back-and-forth between the browser and the server just for updating a single UI element. (Which, while it would be slow enough that you'd notice it, it would be a terrible UX.) So in this case you'd want to move the code to JavaScript, which has the benefit of not being single-threaded and would update the UI as you expect it to.
You can add a panel and then add textboxes onto it
Random random = new Random();
for (int i = 0; i <50; i++)
{
TextBox t=new TextBox();
int randomNumber = random.Next(100, 150);
t.Text = randomNumber.ToString();
panel.Controls.Add(t);
}
You should you separate thread and calculate numbers there and update UI then, because now your UI will be updated after calculation is finished.
E.g. BackgroundWorker
If you want to show each number in the text box, you will need an additional thread which will run the code you have inside button1_Click. With your current implementation, the GUI will freeze while executing the content. As it's very quick you won't notice it though.
From the additional thread, call invoke when setting txt3 to synchronize with the GUI thread. And add a Thread.Sleep(1000) or similar in the for loop in order to see the numbers change.

Categories