troubles threads in winforms - c#

I need to calculate sum of elements in the textbox and number of elements at the same time. So I decided to create two threads - one for length of the number, and one for sum of elements. But when I start only one thread - it works correct. But when I start the second thread - form begins to work slow or stops working at all.
I create two threads
thrd = new Thread(GetLength);
thrd.Start();
thrd1 = new Thread(SetSum);
thrd1.Start();
And these are threads' functions for calculation length of the number in textbox and for calculation sum of its elements.
private void SetSum()
{
while (true)
{
if (this.label3.InvokeRequired)
this.Invoke(new Action(() => label3.Text = this.GetSum().ToString()));
}
}
private int GetSum()
{
string n = textBox1.Text;
int sum = 0;
for (int i = 0; i < n.Length; i++)
{
try
{
sum += int.Parse(n[i].ToString());
}
catch (FormatException) { };
}
return sum;
}
private void GetLength()
{
while (true)
{
if (this.label2.InvokeRequired)
this.Invoke(new Action(() => label2.Text = " | Length = " + textBox1.Text.Length.ToString()));
}
}
Where is the problem? Synchronization?
I have found a solution - I add Thread.Sleep(1) in while loop in GetLength method

Several problems here.
The task at hand is much too small for a (full) Thread. Threads are expensive to create.
By Invoking the main action, all work is done on the Main thread. Your solution is not multi-threaded after all.
Counting is easily done as a by-product of Summing (or vice versa) so 2 threads/tasks is overkill.
The while(true) ... loop will drag your process down, consuming too much CPU time for nothing
The simple answer here is not to use any threads, just run some logic in textBox1.TextChanged.

Yes, the problem is in fact synchronization: there's too much of it.
You're spawning threads that only do Invokes, which means the UI thread is doing all the work.

This part of your code is an infinite loop without any Thread.Sleep or any other Wait. This will bring CPU to 100%. You should tie this to some event or any other activity which will trigger GetLength
private void GetLength()
{
while (true)
{
if (this.label2.InvokeRequired)
this.Invoke(new Action(() => label2.Text = " | Length = " + textBox1.Text.Length.ToString()));
}
}

Related

How to execute threads every min correctly?

This question is in two parts.
I have a console application that gets info from several servers and saves this info to a DB. In order to enabel that this executes simultaniously i have used threads. I am trying to make this execution automatic every minute.
Searching stackoverflow i found that this could work:
var timer = new System.Threading.Timer((e) =>
{
var models = ServerHandler.GetServerModels();
foreach (var m in models)
{
ServerHandler.MakeThreads(m);
}
Console.WriteLine("Running...");
Console.WriteLine("Press 'X' to exit or close the window, i : " + i);
i++;
}, null, 0, TimeSpan.FromMinutes(1).Seconds);
However this is not working as anticipated, it only executes once. If i change to for example this:
TimeSpan.FromMinutes(0.5).Seconds
Or:
TimeSpan.FromSeconds(30).Seconds
Then it works.
What am I doing wrong?
Second part of this question:
When this actually works as I showed above something else happens.
The process runs continuously and after 474 threads it crashes and says that the system is out of memory.
I tried using thread sleep for this but when i do that it stops executing after it has runed once.
Including this if it might help:
public static void MakeThreads(ServerModel model)
{
Thread thread = new Thread(() => SaveServerInfo(model));
thread.Start();
//Thread.Sleep(1);
//thread.Join();
}
How can I make this work?
In your first problem using the .Seconds will only return the seconds value, but you are defining the minutes value as .5, so seconds will always be zero.
If you want to return the seconds you need to use TotalSeconds
TimeSpan.FromMinutes(0.5).TotalSeconds
and in the timespan you are using you are supposed to define the milliseconds. So you're getting a huge number of threads because its running every 30 millseconds instead of every 30000 milliseconds.
So use
TimeSpan.FromMinutes(0.5).TotalMilliseconds
or what i always find easier
(int)(1000 * 60 * 0.5) // Then you just replace the 0.5 with the number of seconds.
Basically a timer does exactly what it's supposed to do: run your code every 0.5 seconds. :) An in your case, that's a problem...
(Please check for syntax errors etc, I'm writing this in notepad)
Long solution
Your problem seems to be that you don't control your threads. Here's how I'd solve it: (This long solution shows how it more or less works)
while (true)
{
// we want to run it again in 0.5 seconds.
DateTime start = DateTime.UtcNow.AddSeconds(0.5);
Thread[] threads = new Thread[models.Count];
for (int i=0; i<models.Count; ++i)
{
threads[i] = new Thread((a) => SaveServerInfo((ServerModel)a));
threads[i].Start(models[i]);
}
for (int i=0; i<models.Count; ++i)
{
threads[i].Join();
}
DateTime current = DateTime.UtcNow;
if (current < start)
{
Thread.Sleep(start.Subtract(current));
}
}
Short solution
However, this might give you issues as well: you might spawn too many threads. This can be solved with a mechanism called thread pooling. As it turns out, there's a simple way to solve this:
static void DoStuff(string s)
{
// change to a value > 0.5 as well to ensure everything works
Thread.Sleep(TimeSpan.FromSeconds(0.1));
Console.WriteLine(s);
}
static void Handle(List<string> models)
{
while (true)
{
// we want to run it again in 0.5 seconds.
DateTime start = DateTime.UtcNow.AddSeconds(0.5);
Parallel.ForEach(models, (a) => DoStuff(a));
DateTime current = DateTime.UtcNow;
if (current < start)
{
Thread.Sleep(start.Subtract(current));
}
}
}
static void Main(string[] args)
{
List<string> models = new List<string>();
for (int i = 0; i < 10; ++i)
{
models.Add(i.ToString());
}
Handle(models);
}

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).

Display number as it is found

I have simple task in my app, but i have problem.
For example:
for (int i = 1; i <= 1000000; i++)
{
if (i % 2 == 0) {
TextBlock.Text += string.Format("{0},", i);
}
}
While app doing that task it takes long time, so I would like it displays number when it is found and not at the end, all numbers together.
What is the simplest way to do that for newbie like me?
It is WP8, C#.
Thanks a lot.
you can keep adding these numbers in a queue object and have a thread looking for a change in the queue object and simultaneously update the textbox.
So the problem is, that UI doesn't get refreshed until your loop end, even if you are appending text to TextBox. The easy way to fix it - is to add Application.DoEvents() call after TextBlock.Text += string.Format("{0},", i);.
But it has some critical downsides (explained here https://stackoverflow.com/a/5183623/2152334).
The right way is to do calculation in a different thread (using Tasks for example) and update UI thread using Dispatcher:
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
TextBlock.Text += ...
});
You can't refresh the display if your code blocks the UI thread. You need to leave the UI thread for your long task.
// We go to a non-UI thread
TaskEx.Run(() => {
for (int i = 1; i <= 1000000; i++)
{
// some long operation here... -_-"
if (i % 2 == 0)
{
// We return to UI thread after long operation to display the result
Deployment.Current.Dispatcher.InvokeAsync(() => {
TextBlock.Text += string.Format("{0},", i);
});
}
}
});
Also you might consider adding a cancellation token to break the loop in case the user leaves the page being displayed.
[edit: this solution is meant for your comment "my app will display few numbers but calculation takes long time". If you really need 1000000 results, try to Dispatcher.InvokeAsync(...) and TextBlock.Text += ... multiple results at a time.]

stopwatch c# behave differently in different threads?

I'm currently using a stopwatch as a global timer. I have main thread running, another thread, and an event method.
The main thread launches the other thread and the event method is triggered by events. Both methods will call the stopwatch and get its time. The thing is, the times are not consistent:
from main thread:
START REC AT 9282
STOp REC AT 19290
from another thread:
audio 1
audio 304
audio 354
audio 404
audio 444
audio 494
audio 544
audio 594
from event method:
video 4
video 5
video 29
video 61
video 97
video 129
video 161
I don't get why if i start my rec at 9282, the other two functions that call the stopwatch will have timers that start at zero? Is this a thread related issue? How can i fix this? Thanks
UPDATE:*********
when i save my frames i changed to:
long a = relogio.EllapseMilliseconds
i print out this value and its ok, as expected. but when i print the value stored in the lists, they come as starting from the beggining. strange huh?
SORRY FOR ALL THE TROUBLE, I PRINTED IT WITHOUT THE STARTING TIME,THATS WHY THEY ALL SEEMED TO START FROM ZERO! MANY THANKS AND SORRY!
main thread
private void Start_Recording_Click(object sender, RoutedEventArgs e)
{
rec_starting_time = relogio.ElapsedMilliseconds;
Console.WriteLine("START REC AT " + rec_starting_time);
write_stream.enableRecording();
Thread a = new Thread(scheduleAudioVideoFramePicks);
a.Start();
scheduleAudioVideoFramePicks - this thread just counts the time, so i know when to stop
//while....
if (rec_starting_time + time_Actual > rec_starting_time+recording_time * 1000)//1000 - 1s = 1000ms
{
totalRecordingTimeElapsed = true;
write_stream.disableRecording();
Console.WriteLine("STOp REC AT " + relogio.ElapsedMilliseconds);
}
//end while
lock (list_audio)
{
int b = 0;
//print time of frames gathered
foreach(AudioFrame item in list_audio){
Console.WriteLine("audio " + (item.getTime() - rec_starting_time));
}
lock (list_video)
{
}
foreach (VideoFrame item in list_video)
{
Console.WriteLine("video " + (item.getTime() - rec_starting_time));
}
}
the another thread, where i get the time
if (write_stream.isRecording())
{
list_audio.Enqueue(new AudioFrame(relogio.ElapsedMilliseconds, audioBuffer));
}
event method
if (write_stream.isRecording())
{
list_video.Add(new VideoFrame(relogio.ElapsedMilliseconds, this.colorPixels));
}~
i dont know if this is relevant, but i start my stopwatch like this
public MainWindow()
{
InitializeComponent();
//some code
this.relogio = new Stopwatch();
relogio.Start();
}
Stopwatch is not threadsafe, particularly for 32-bit programs.
It uses the Windows API call QueryPerformanceCounter() to update a private long field. On 32-bit systems you could get a "torn read" when one thread reads the long value while another thread is updating it.
To fix that, you'd have to put a lock around access to the Stopwatch.
Also note that one some older systems there were bugs where inconsistent values could be returned from different threads calling QueryPerformanceCounter(). From the documentation:
On a multiprocessor computer, it should not matter which processor is called. However, you can get different results on different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL). To specify processor affinity for a thread, use the SetThreadAffinityMask function.
I have never encountered this bug myself, and I don't think it's very common.
What results do you get with the following test program? The times should be mostly increasing in value, but you are liable to get one or two out of order just because their threads get rescheduled just after they've read a value and before they add it to the queue.
namespace Demo
{
class Program
{
Stopwatch sw = Stopwatch.StartNew();
object locker = new object();
ConcurrentQueue<long> queue = new ConcurrentQueue<long>();
Barrier barrier = new Barrier(9);
void run()
{
Console.WriteLine("Starting");
for (int i = 0; i < 8; ++i)
Task.Run(()=>test());
barrier.SignalAndWait(); // Make sure all threads start "simultaneously"
Thread.Sleep(2000); // Plenty of time for all the threads to finish.
Console.WriteLine("Stopped");
foreach (var elapsed in queue)
Console.WriteLine(elapsed);
Console.ReadLine();
}
void test()
{
barrier.SignalAndWait(); // Make sure all threads start "simultaneously".
for (int i = 0; i < 10; ++i)
queue.Enqueue(elapsed());
}
long elapsed()
{
lock (locker)
{
return sw.ElapsedTicks;
}
}
static void Main()
{
new Program().run();
}
}
}
Having said all that, the most obvious answer is that in fact you aren't sharing a single Stopwatch between the threads, but instead you have accidentally started a new one for each thread...

Starting two threads runs them in sequence and not at the same time

I have a main thread which is controlling a windows form, upon pressing a button two threads are executed. One is used for recording information, the other is used for reading it. The idea behind putting these in threads is to enable the user to interact with the interface while they are executing.
Here is the creating of the two threads;
Thread recordThread = new Thread(() => RecordData(data));
recordThread.Name = "record";
recordThread.Start();
Thread readThread = new Thread(() => ReadData(data));
readThread.Name = "read";
readThread.Start();
The data is simply a Data-object that stores the data that is recorded during the recording.
The problem that I am facing is that the first thread is executed fine, the second refuses to run until the first one completes. Putting a breakpoint in the second threads function, ReadData lets me know that it is only called after the first thread is done with all of its recording.
I have been trying to solve this for a few hours now and I can't get my head around why it would do this. Adding a;
while(readThread.IsAlive) { }
right after the start will halt the execution of anything after that, and it's state is Running. But it will not go to the given method.
Any ideas?
Edit:
The two functions that are called upon by the threads are;
private void RecordData(Data d)
{
int i = 0;
while (i < time * freq)
{
double[] data = daq.Read();
d.AddData(data);
i++;
}
}
private void ReadData(Data d)
{
UpdateLabelDelegate updateData =
new UpdateLabelDelegate(UpdateLabel);
int i = 0;
while (i < time * freq)
{
double[] data = d.ReadLastData();
this.Invoke(updateData, new object[] { data });
i++;
}
}
The data object has locking in both the functions that are called upon; ReadLastData and Read.
Here are the methods in the Data object.
public void AddData(double[] data)
{
lock (this)
{
int i = 0;
foreach (double d in data)
{
movementData[i].Add(d);
i++;
}
}
}
public double[] ReadLastData()
{
double[] data = new double[channels];
lock (this)
{
int i = 0;
foreach (List<double> list in movementData)
{
data[i] = list[list.Count - 1];
}
}
return data;
}
Looks like you have a race condition between your reading/writing. In your first thread you lock down the object whilst you add data to it and in the second thread you attempt to get an exclusive lock on it to start reading. However, the problem is the first thread is executing so fast that the second thread never really gets a chance to acquire the lock.
The solution to this problem really depends on what sort of behaviour you are after here. If you expect after every write you get a consecutive read then what you need to do is control the execution between the reading/writing operations e.g.
static AutoResetEvent canWrite = new AutoResetEvent(true); // default to true so the first write happens
static AutoResetEvent canRead = new AutoResetEvent(false);
...
private void RecordData(Data d)
{
int i = 0;
while (i < time * freq)
{
double[] data = daq.Read();
canWrite.WaitOne(); // wait for the second thread to finish reading
d.AddData(data);
canRead.Set(); // let the second thread know we have finished writing
i++;
}
}
private void ReadData(Data d)
{
UpdateLabelDelegate updateData =
new UpdateLabelDelegate(UpdateLabel);
int i = 0;
while (i < time * freq)
{
canRead.WaitOne(); // wait for the first thread to finish writing
double[] data = d.ReadLastData();
canWrite.Set(); // let the first thread know we have finished reading
this.Invoke(updateData, new object[] { data });
i++;
}
}
Could you try adding a Sleep inside RecordData?
Maybe it's just your (mono cpu??) windows operating system that doesn't let the second thread get its hand on cpu resources.
Don't do this:
lock (this)
Do something like this instead:
private object oLock = new object();
[...]
lock (this.oLock)
EDIT:
Could you try calls like this:
Thread recordThread = new Thread((o) => RecordData((Data)o));
recordThread.Name = "record";
recordThread.Start(data);

Categories