PDA

View Full Version : C# have a seperate draw thread for the application.


elkinm
08-10-2010, 12:01 PM
I noticed a while ago that form applications are very slow to draw. When I minimize/ maximize or go over it with another window, I can see the form components redrawn and/or I can erase the form for a second or so.
I was told it is because the same thread draws and does everything else, the drawing is slow. I was also told if I make the main thread to nothing but draw and another thread do everything else, the drawing would be fast without affecting my application performance.

I tried usning worked threads based on this page: http://www.daveoncsharp.com/2009/09/create-a-worker-thread-for-your-windows-form-in-csharp/

This is my code:

public partial class Form1 : Form
{
private Thread workerThread = null;

private bool stopProcess = false;
private delegate void UpdateStatusDelegate();
private UpdateStatusDelegate updatedtatusdelegate = null;


public Form1()
{
InitializeComponent();
this.updatedtatusdelegate = new UpdateStatusDelegate(this.UpdateStatus);
}

private void UpdateStatus()
{
this.textBox1.Text += "*";
}

private void HeavyOperation()
{
for (int i = 0; i < 10000000; i++)
{ // POSSIBLE BREAK POINT HERE
if (!this.stopProcess)
{
this.Invoke(this.updatedtatusdelegate);
}
else
{
this.workerThread.Abort();
}
if (i == 100000|| i == 9000000)
{ //BREAK POINT HERE
}
}
}

private void button1_Click(object sender, EventArgs e)
{
this.stopProcess = false;

this.workerThread = new Thread(new ThreadStart(this.HeavyOperation));
this.workerThread.Start();
}

private void button2_Click(object sender, EventArgs e)
{
this.stopProcess = true;
}
}

This is not quite what I had in mind. First of all, the code as is runs very slowly, posibly hours because updating the main delegate and having it draw the extra * takes forever, exactly what I need to avoid.
If you comment out the first if else in the heavyworker you will notice that the entire 10000000 iterations takes less than a second, so simply updating the main thread and having it draw slows it down and absurd amount of times.

First, is there a way to have it update, but only draw to the screen maybe once a second or so like the Application.ScreenUpdating = False in excel VBA so it will run fast and still draw to the screen regularly.

Also, if you have a break point in the break point or possible break point spots in the code and it is stopped, the window stops drawing. The whole point of this is that I want drawing to be completely separate from the underlying operation, so it would continue drawing what was last on the screen even if I am debugging, or the application busy.

I know it can be done as I have seen .NET applications which were very fast without the mentioned drawing issues or delays and without slowing down the application.

Can anybody help me modify this basic code to run like I want to?

Also, this is less important, but I would like the text box to show the number of the current iteration, not a series of stars so I need to send the int i to the delegate which I have also been trying to do.

Thanks,
elkinm.

nickbits
08-10-2010, 12:06 PM
don't call the delegate on each iteration

elkinm
08-10-2010, 12:11 PM
That is true, but by the underlying reason I need this, I need to know where the worker is at all times, I just don't need to draw it. Also, another major concern is that I need the main window to continue to be drawn if I have break point or pause in the worker thread which also does not happen.

Thanks again.

nickbits
08-10-2010, 12:17 PM
just use class variable(s) and protect them with lock() { } statements.

When a breakpoint is encountered all threads are paused, I don't think there is any way around that, unless you spawn a separate process for your "work".

Cogman
08-10-2010, 12:20 PM
Yep, the use of a delegate in this situation is VERY inefficient. A much more efficient method would be to output to a shared string in the class and have the GUI grab the string and display it after each refresh. Right now, you are essentially waiting for each refresh to process the next loop.

elkinm
08-10-2010, 12:26 PM
Sorry, if I sound stupid, but I don't know what you mean by class variables (just global class variables) and lock statements?

I understand that breaking may pause all threads, what I need to see what the windows was displaying, I am short on screen space and when a break point is reached VS goes over the program and it is grayed out. I need to see the last visual state of the application before the break point. Once again, I have seen it done so I know it can be done, I just don't know how.

Thanks

ObscureCaucasian
08-10-2010, 12:31 PM
Also you can turn on double buffering, which would draw the entire form on one window and then swap it all at once as opposed to drawing on the same canvas that is on the screen. Sounds like it's slow enough he'll have "frame-rate" issues though.

elkinm
08-10-2010, 12:33 PM
Yep, the use of a delegate in this situation is VERY inefficient. A much more efficient method would be to output to a shared string in the class and have the GUI grab the string and display it after each refresh. Right now, you are essentially waiting for each refresh to process the next loop.

Do you mean keep a variable in the class and update the variable in that class without calling the delegate?

I will try that, however, how will the update class know that the variable has changed and needs to draw it?

Also, in this case everything is in the single form class. What if I have multiple classes and multiple custom forms, the calculation is fast, but I still need all the drawing to be efficient and only done in the main thread.

Thanks again.

ObscureCaucasian
08-10-2010, 12:39 PM
I think he's getting at something like:


String s = "";

...

private void HeavyOperation()
{
for (int i = 0; i < 10000000; i++)
{ // POSSIBLE BREAK POINT HERE
if (!this.stopProcess)
{
s += "*";
}
else
{
this.workerThread.Abort();
}
if (i == 100000|| i == 9000000)
{ //BREAK POINT HERE
}
}
}

...

public override void OnPaint(PaintEventArgs e) // This signature might be wrong...
{
this.textBox1.Text = s;
base.OnPaint(e);
}

Cogman
08-10-2010, 12:39 PM
public partial class Form1 : Form
{
private Thread workerThread = null;
private string _statusString = "";
private string statusString
{
get
{
lock(this)
{
return _statusString;
}
}
set
{
lock(this)
{
_statusString = value;
}
}
}
private bool stopProcess = false;


public Form1()
{
InitializeComponent();
}

private void HeavyOperation()
{
for (int i = 0; i < 10000000; i++)
{ // POSSIBLE BREAK POINT HERE
if (!this.stopProcess)
{
statusString += '*';
}
else
{
this.workerThread.Abort();
}
if (i == 100000|| i == 9000000)
{ //BREAK POINT HERE
}
}
}

private void button1_Click(object sender, EventArgs e)
{
this.stopProcess = false;

this.workerThread = new Thread(new ThreadStart(this.HeavyOperation));
this.workerThread.Start();
while (workerThread.IsAlive)
{
this.textBox1.Text = statusString;
Application.DoEvents();
}
}

private void button2_Click(object sender, EventArgs e)
{
this.stopProcess = true;
}
}


This is essentially what I mean.

nickbits
08-10-2010, 12:39 PM
Do you mean keep a variable in the class and update the variable in that class without calling the delegate?

I will try that, however, how will the update class know that the variable has changed and needs to draw it?

Also, in this case everything is in the single form class. What if I have multiple classes and multiple custom forms, the calculation is fast, but I still need all the drawing to be efficient and only done in the main thread.

Thanks again.

Use a timer to update the display.

Cogman
08-10-2010, 12:41 PM
Use a timer to update the display.

:) no timer necessary if you do it like I did.

nickbits
08-10-2010, 12:46 PM
:) no timer necessary if you do it like I did.

True but I doubt the performance will be much better than what he already had. Also DoEvents is to be avoided. I wasn't aware it still existed in WinForms :S. Guess they had to appease the VB6 guys.

elkinm
08-10-2010, 12:46 PM
Also you can turn on double buffering, which would draw the entire form on one window and then swap it all at once as opposed to drawing on the same canvas that is on the screen. Sounds like it's slow enough he'll have "frame-rate" issues though.

Double buffering is a good idea and it does help the application show up all at once, however, maybe I am just seeing things, but it still seems to be a little sluggish, possibly because the drawing process still takes to long before it does the swap. Instead of seeing the controls show up one by one or line by line the whole thing shows up at once, but it only shows up after everything is drawn so I think it seems even slower.

The ultimate goal is still to have all the calculations separate updating values in the form as needed, and sending them to the main thread and then the main thread simply draws them quickly and efficiently on it's own.

Cogman
08-10-2010, 12:50 PM
True but I doubt the performance will be much better than what he already had. Also DoEvents is to be avoided. I wasn't aware it still existed in WinForms :S. Guess they had to appease the VB6 guys.

It isn't about performance, my method terminates automatically without causing issues. A timer method would be prone to non-termination issues.

As for the DoEvents function... I don't really see why it is that big of an issue. If you want to update a form in the middle of a complex loop, it works well.

ObscureCaucasian
08-10-2010, 01:12 PM
It isn't about performance, my method terminates automatically without causing issues. A timer method would be prone to non-termination issues.


Could you elaborate on this by chance?

Cogman
08-10-2010, 01:18 PM
Could you elaborate on this by chance?

Certainly. If you set a timer and the thread finishes before the timer does, you have to specifically terminate the time. It could be especially troubling if you have a timer that sets itself up on termination. While this might not be too big of an issue here, in other situations, tracking and stopping update timers can be a real pain.

The method I proposed is guaranteed to terminate when the thread finishes executing. It doesn't use timers, it simply frequently updates the text box and uses "DoEvents" to ensure that the screen gets redrawn before doing the next update. It might suffer an Off-by-one error, however, that would be easily fixed by updating the textbox afterwords.

If you are really paranoid about using DoEvents, then you could spawn a new thread that does essentially the same thing without the "doEvents" Though, I would suggest throwing in a yield to avoid wasteful Cycle consumption.

Markbnj
08-10-2010, 02:09 PM
In general if you create a thread and run it in a tight loop as in your test case, then it's going to want 100 percent of one core. If you have a single core machine that is going to leave little time for the other application threads. Even if you have multiple cores it will generally run more slowly than, say, a more typical scenario where a thread responds to an event, does some work, and exits. Priority plays into it as well. Windows scheduling is an arcane topic that I don't understand well, but I believe that there is some overall budget for a given process at a given priority, and if you create one thread that is constantly running full speed then that has to impact the time alloted to the other threads in the process.

Unless you have some complex requirement that you haven't elaborated on yet, I would stick with the normal approach, i.e. create a worker thread to manipulate your model classes, leave the main thread alone to manage the UI updates, create an event on the model class that the UI can subscribe to that reflects when an update occurs. You can use a couple of different techniques to make sure the event occurs on the UI thread, including InvokeRequired/BeginInvoke, and the Event-based async pattern. See the posts on this Stack Overflow thread as an entry point:

http://stackoverflow.com/questions/6184/how-do-i-make-event-callbacks-into-my-win-forms-thread-safe

The basic flow looks like:

1) UI subscribes to StuffChanged event on model class
2) initiating event occurs on UI thread
3) worker thread spawned and begins working
4) UI thread event handler returns
5) worker thread changes some data
6) worker thread raises event on UI thread (using techniques just discussed)
7) event handler registered in (1) is entered on the UI thread
8) UI updates control properties from the model class
9) UI thread exits event handler
10) worker thread either continues working or has exited

I would not use timers, or any design that requires the UI thread to loop and check a state flag. The whole winforms model depends on your doing something brief with the UI thread in response to an event, and then letting it go.

Note that in many real world scenarios you don't need ongoing updates from the worker thread to the UI thread. In these cases the flow is spawn worker, wait for it to finish, update UI from model. That probably covers 80 percent of the cases we usually encounter, and it's a lot easier as BackgroundWorker already has the internal plumbing to fire RunWorkerCompleted on the creating thread.

elkinm
08-10-2010, 03:54 PM
Sorry, I had to do something for a while.

I would like to clarify what exactly I need, the implementation is not really important, just that I can understand how it works and how to add it to my code.

As a basis for most of my coding lets start with Excel and VBA.
If I make an iteration to go from 0 to 10000 (to start) or the same 1000000 and write the result to cell A1.
If I just run it, I can see the number increasing in the cell and it takes a while to complete.
Now I add Application.ScreenUpdating = False fefore the loop and Application.ScreenUpdating = true after. Now when I run the macro, for 10000 the result shows up almost instantly, for 10000000 it takes much longer, a few minutes, but is still much faster then if screen updating was on.
And the kicker, when it is running, Excel is basically frozen as it is single threaded, however, if I drag the window around or drag a window over it I still see all the Excel contents, it does not turn white until the calculation is finished. This is a big part of what I want, drawing independent of the application. (Excel can loose drawing in many cases but it is still quite resilient and I want my app to be at least as resilient.

As far as the actual application. I have a basic form which contains a TableLayoutPanel (10 x 10 or more) and each cell of the layout panel contains a custom controls and that control has a stop and start button as the application so far and a text box showing the current loop counter.
In the main form there are start and stop buttons which start and stop all the counters at once. Each counter can be started or stoped seperately but the buttons in that control.

The goal, the GUI must be robust, I cannot erase it or visually see it be slow if I minimize or maximize it or drag a window over it. Each control must be aware of the counter state it is on and update it's text box, and the main application should be able to query the counter of any control at any time, however, there is no need to display all the numbers in each form to the user and the displayed number can be behind.
The application itself must also be fast, ideally as fast as the loop was when it was not updating the main display.

My though was to have the draw thread or something and it draws what is needed, just Like the Excel window even when running the macro. Excel with screen updating draws every single update, I could enable and disable screen updating every 1000 or so updates which would still be much faster and give me periodic updates, but I don't think C# requires the same approach. As far as I understand, as long as all variable are local and nothing is drawn to the screen, there is no reason why all the loops should complete almost instantly I can have a global integer and update it with i every time and the loop finishes just as fast, then I can display the final value.

In the event the thread takes longer or is slower then I would like to see periodic updates on the screen, as I mentioned, the displayed value can be way off from actual, but internally the program knows where it is at any time and react accordingly.

Once again, the application must be very fast, look fast and be responsive to button clicks.

I thought multi-threading was the solution but if there is a better way I am all for it.

Sorry for being such a pain. I am still trying to figure out all the previous posts.

Thanks again everyone, hopefully this helps a little.

Cogman
08-10-2010, 04:09 PM
The key to good multithreading is keeping threads as separate as possible. The more threads have to communicate with each other, the bigger the slowdown you will see. Now, with windows, you pretty much are bound to have one thread handle all gui stuff (I don't know if it is impossible, though I have looked, but as far as I can tell only the thread that created a windows resource can access it. IE a DC).

After that, to make things feel fast, you'll want to have background threads do all the work, and then update when the thread is done. To keep things fluid, you'll want to avoid getting status updates from the thread.

elkinm
08-10-2010, 04:13 PM
To add a little, I just changed the loop to set a global variable to val and call the delegate which updates the text box. I noticed that the updates to the screen are slower this way then with Excel.

Then I simply changed the delegate to not update the textbox until the high values and it is very fast, at least up until then.

Now I could have the delegate itself only update in increments, and have the worker run full speed, but I still think it is to involving and I don't want the worker to stop or slow down when I am updating the screen.

I tried adding the OnPaint event as mentioned earlier, but I got a compile error at buildtime but not before saying cannot change access modifiers when overriding protected inherited member ...
The strange part is that if I block comment out the method, the error remains and OnPaint remains highlighted until I restart VS. Any ideas why this is?

elkinm
08-10-2010, 04:27 PM
The key to good multithreading is keeping threads as separate as possible. The more threads have to communicate with each other, the bigger the slowdown you will see. Now, with windows, you pretty much are bound to have one thread handle all gui stuff (I don't know if it is impossible, though I have looked, but as far as I can tell only the thread that created a windows resource can access it. IE a DC).

After that, to make things feel fast, you'll want to have background threads do all the work, and then update when the thread is done. To keep things fluid, you'll want to avoid getting status updates from the thread.


That is what I am trying to do have one, the main thread do all the drawing. While all calculation and updating is done in another thread. What I am worried about is since I create different forms in the TableLayoutPanel, I need to create all of these in the main thread before having worker threads, I also need to have the other thread handle events between all classes and I don't know how to create one worker thread for it all.

Something entirely different. I recently started using tables and DataGridViews, so I am going to try instead of a textbox, simply have a grid and a table with only one cell and set the data source. I am hoping it should be fast.
At the same time if VS can make this link fast then I don't see why I can't do the same with my one code.

Cogman
08-10-2010, 04:36 PM
That is what I am trying to do have one, the main thread do all the drawing. While all calculation and updating is done in another thread. What I am worried about is since I create different forms in the TableLayoutPanel, I need to create all of these in the main thread before having worker threads, I also need to have the other thread handle events between all classes and I don't know how to create one worker thread for it all.

So long as you aren't overdoing it (IE create a thread for 1 + 1), threads are relatively cheap to make. Just make a new thread when you need it, don't worry about having one worker thread for everything.

However, if you really, really, care about performance, and what to do a lot of little tasks threaded. Then the C# threadpool might be what you are looking for
http://msdn.microsoft.com/en-us/library/3dasc8as(VS.80).aspx

elkinm
08-10-2010, 04:50 PM
So long as you aren't overdoing it (IE create a thread for 1 + 1), threads are relatively cheap to make. Just make a new thread when you need it, don't worry about having one worker thread for everything.

However, if you really, really, care about performance, and what to do a lot of little tasks threaded. Then the C# threadpool might be what you are looking for
http://msdn.microsoft.com/en-us/library/3dasc8as(VS.80).aspx

I will take a look at it.

I did try the gridview method and it was just as slow as the textbox, I was hoping grid updates would be properly throttled.

So it seems it still updates the table and then has to wait for it to be drawn.

So I think what I really need is simply to somehow make drawing completely independent, like out of order execution, I send an update to the table or variable, but instead of drawing it right away it waits until it is supposed to, possibly a screen refresh. The value can be updated before the screen refresh so when the screen does refresh the latest known value is displayed.

elkinm
08-10-2010, 07:30 PM
I tried the same code on my home PC with VS 2010. At work I have 2008.
Anyway, the screen updating is much faster but still very slow. However, on my work PC the invoke operations have little to no effect on performance at least when nothing is updated on the screen, but on my PC the is a significant slowdown.

I will try saving the time the last time the view was updated and not update for 1 or so seconds which should reduce the update frequency however it is still not very efficient and I miss the last update.
For the data table I need to try setting the source to null and setting to a value only when needed to see if that helps.

The problem is that all these methods only work around the problem. The key is have drawing and screen updating slowed than the code updates values. I need to skip values on the screen as frames with video playback.

elkinm
08-11-2010, 08:42 AM
I have tried using BeginInvoke instead of invoke which kind of works.

The good news is that the iteration loop finishes as fast as ever. But then the program stays handling all the updates for a while.

Also memory usage goes through the roof with BeginInvoke. I have been unable to use EndInvoke or understand and utilize all the online examples I found so far.

Now there just needs to be a async way to push to the display and draw, but allow skipping data so only the latest value is displayed like a video with dropped frames.

Cogman
08-11-2010, 08:54 AM
look, your problem is that you are trying to draw the results for each iteration. DON'T DO THAT. If you want speed and responsiveness, drop invoke all together and go with a class variable to take care of the state of the thread. If you try and render every iteration, you are going to slug your program. Screen rendering IS SLOW.

When you use BeginInvoke, you are essentially just spawning a new thread for each iteration (1mb is generally used per thread). Drop invoke all together, it is destroying your performance.

elkinm
08-11-2010, 09:10 AM
Rendering to the screen is meaningless as are the iterations. I don't need any of it in my acual code, I just need to render anything, even one instance, without slowing down my code.

Enver if I render only once at value 1000000 that 1 render can take more time then the entire loop and kill performance, just 1. I need a way to make all rendering asyncronus so the code can continue.

In my real code I am going through live data in real time, lets say network data and I need to show number of packets seen in second increments. Just 1 render kills my speed.

Thanks again,

Cogman
08-11-2010, 09:34 AM
Rendering to the screen is meaningless as are the iterations. I don't need any of it in my acual code, I just need to render anything, even one instance, without slowing down my code.

Enver if I render only once at value 1000000 that 1 render can take more time then the entire loop and kill performance, just 1. I need a way to make all rendering asyncronus so the code can continue.

In my real code I am going through live data in real time, lets say network data and I need to show number of packets seen in second increments. Just 1 render kills my speed.

Thanks again,

What you are doing, right now, by using the invoke is creating a thread and then making it wait until rendering is done. You don't have one thread doing rendering and one thread doing computations, you have one thread doing rendering and one thread that waits on the one thread to do rendering.

Remove the Invoke. Use shared memory to pass data rather then calling an invoke. I don't know how I could be clearer. Invoke blocks one threads execution and waits for the next to complete. That means that your computations thread is waiting for the rendering thread to complete.

You need a lazy model. Data gets stored in memory (not in a rendered element) One thread renders the data as fast as possible while the other does computations as fast as possible. The thread doing the rendering wont always display exactly what the computations thread is doing, but that doesn't matter, rendering is more for the user and less about accurate computations.

I realize that rendering is meaningless in your example, and what I am saying is right now you are rendering EVERYTHING, not just something. That slows things down tremendously.

elkinm
08-11-2010, 11:55 AM
I took out the Invoke, however the invoke itself does not slow down the application nearly as much if I don't do any painting but still slower.

I made my datagrid virtual and added a form timer as mentioned earlier. So I update the table only on timer events which then is drawn to the table exactly as mentioned earlier.

The timer iterates every 10 ms now and it is much faster than before, but still slower then if no painting is involved. I am also trying to paint differently and have the grid pull the data. Have the timer invalidate the cell and then on the next cellvalueneeded have it pull the value, which should be fater then updates from the data table however it does not work yet.

This also puts me with a timer. Interestingly enough changing the timer from 10 to 100 does nothing to performance. I would expect it to become 10 times faster. Also, your method with the Application.DoEvents() loop works pretty much at the same speed as the timer but slightly faster. Both timers take about .95 seconds for 100 million iterations but the application.doevents takes about .85 seconds.
I do find it interesting that the loop is faster, but DoEvents lets other threads run and only continues when it is started next. However does that mean that the main thread cannot continue when the while loop is going, in the case that I have 2 worker threads? Then again, I can monitor both threads for activity.

It is much fasted now using very early suggestions. I am still trying to make it better and smoother.

Thanks again.

Cogman
08-11-2010, 11:58 AM
Ok, here is a demo of what I'm talking about.
http://rapidshare.com/files/412363086/WpfApplication1.zip

It has three buttons to demonstrate fast updating, slow updating, and medium updating (the medium and fast updating methods are ~ the same speed).

(there are no viruses, but if you don't trust me still, the source is included in the file.)

elkinm
08-11-2010, 12:17 PM
Thanks, I can't run the application I have VS 2008 at work and it does not want to open it. I will try it tonight.

Cogman
08-11-2010, 12:19 PM
Thanks, I can't run the application I have VS 2008 at work and it does not want to open it. I will try it tonight.

I didn't do any .net 4.0y things in there, so just start a new project and import the necessary files.

elkinm
08-11-2010, 01:16 PM
Still not working, I don't see anyhting in the files other than the basic constructor.

How does a WPF application differ from forms?

Cogman
08-11-2010, 01:18 PM
Still not working, I don't see anyhting in the files other than the basic constructor.

How does a WPF application differ from forms?

It is a forms application (unless I got the wrong one.. Just a sec.)

Cogman
08-11-2010, 01:20 PM
http://rapidshare.com/files/412376161/ThreadingDemo.zip

Yep, I got the wrong one. Sorry about that. (The difference between WPF and forums is mostly about the style of creating windows. WPF is a more HTML like window creation environment)

elkinm
08-11-2010, 03:10 PM
Thanks, this one works fine. A couple questions though. In the fast thread you don't have Application.DoEvents and I tried taking it out of my 100 mil loop and it became really slow so DoEvents gives other threads or events a chance to run. Is it always safe for non critical events or threads?

For the medium timer you have BeginInvoke with the Invoker variable. Is setting the invoker the same as a EndInvoke?

I have also been reading about a fire and forget delegate. Is that the same as BeginInvoke or is it something else and is it faster?


My mistake, without the DoEvents it is slower but only slightly.

Cogman
08-11-2010, 03:22 PM
Thanks, this one works fine. A couple questions though. In the fast thread you don't have Application.DoEvents and I tried taking it out of my 100 mil loop and it became really slow so DoEvents gives other threads or events a chance to run. Is it always safe for non critical events or threads?

For the medium timer you have BeginInvoke with the Invoker variable. Is setting the invoker the same as a EndInvoke?

I have also been reading about a fire and forget delegate. Is that the same as BeginInvoke or is it something else and is it faster?

The lack of the doevents in the faster code was by mistake. Throw it in there and you have what I meant to present (I took it out because I was playing with some things).

The invoker variable is simply there to make sure that you don't have a mile long line of invokes to the main thread. It makes it so that updating appears to go smoothly.

Fire and forget delegates are the ones where you would do something like
BeginInvoke(new delegateVariable(functionName));
where you are making multiple new variables to each delegate function.

BeginInvoke simply returns control back to the thread that called it while it goes off and does its work. Rather then calling an invoke every time in the medium thread, I only call it when the last evoke finishes firing. This allows the thread to go as fast as needed without having to worry that the content isn't being updated properly.

You should note, this isn't the absolute fastest threaded code I can write, rather, this is just an example of how threaded code should be written. To make multiple threads run faster, you generally want locking to be a sort of "last resort" thing (not what I'm doing here). The contention for the lock here will significantly slow things down. If I was going to make this faster, I would have a local variable in the thread, then have that thread attempt to use the lock, if it can't, manipulated the local variable some more until it can obtain the lock, Then update the data protected by the lock with the information from the local variable. This leads to pretty fast threading code because it significantly reduces locking contention. (I don't know how to try locks, so to speak, in c#. In c++ it was a simple TryEnterCriticalSection(CS)).

elkinm
08-11-2010, 04:08 PM
I didn't even notice that the Invoker.IsCompleted at first. I removed the first modulo check and noticed that performance remains the same. The updating itself is the bottleneck and it is great to be able to have the worker let it finish before updating again.

I also have no idea how to test a lock. I will see what I can do, but for now I should not need to do to much locking.

Thanks again.

elkinm
08-28-2010, 11:59 PM
Hi, I was busy so I could not update in a while.

My next step is to load a second form window to change values of the primary program but without blocking the main program.
Here is my solution so far VS 2010 file: http://www.multiupload.com/867Y2HBGI3

The example I was using was from here: http://www.homeandlearn.co.uk/csharp/csharp_s13p1.html

One thing that is very important is that I can always press button1. With the example, the show command can result in multiple windows and if the window blocks, as with a message box, button1 cannot be pressed. The ShowDialog() option always blocks the main form.

In my code I start the second form as it's own application in a new form. And when the form exits, it invokes the primary window to change the text box.

It is working almost perfectly.
the problem happens if I press button2 a second time while the second form is open. Since the second form can be minimized or hidden behind another window, I want pressing button12 a second time to show the second form or bring it to the front. I get a cross-threading error, which surprises me as I am using an invoke to the second thread. And since the entire second application exists in a different thread, I don't understand why any call to form2 does not run in thread2 automatically.

I still cannot get second form to become the front. Any idea what I am doing wrong and why?

Something else that would be nice is that I would like to control where the second window opens, I would like i to be close to the main form, but not blocking ir or at least not button1. And if the form is re-show as above, it should also be moved close to the same form.

I have been going though this: http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k%28EHINVALIDOPERATION.WINFORMS.ILLEGALCROSSTHRE ADCALL%29;k%28TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERSION%3dV4.0%22%29;k%28DevLan g-CSHARP%29&rd=true

to try to use background worker threads, but I don't understand how the basic examples can work and how they can make safe calls between threads?

Thanks again,
elkinm

Mark R
08-30-2010, 05:02 AM
Edit: Original post was talking BS.

The reason your BeginInvoke call is failing is you are trying to invoke a secondForm method on Form1's thread.

In Form1, you call BeginInvoke (secondForm.showformdelegate). However, you haven't explicity specified which object to call BeginInvoke on. As BeginInvoke is a member of Form1, it gets executed as:
Form1.BeginInvoke (blah...) which forces the execution to run in Form 1's thread.

It works fine if you call it as secondForm.Invoke (secondForm.showformdelegate).


Personally, I prefer to put all your forms into a single thread. That way, there is no cross-thread mayhem to deal with.
Then put your workers into separate threads.
See Link (http://www.chumpusrex.com/junk/Test1.rar)

elkinm
08-30-2010, 08:53 AM
You're trying to spawn new threads containing multiple application loops and forms. While this might work, I'm not sure it's how you're meant to do it. In particular, your accessing the 'Application' object from 2 separate threads. That's asking for trouble.

Your cross threading error comes from the fact that your 'Application' object (which is what does the invoking) was originally created on your original thread. But your second form is running in a different thread, and you're trying to use the same 'Application' object to manage your new form.

The simplest way to make your program work is to get rid of 'Application.Run()' on the second form, and replace it with 'secondform.ShowDialog()'. ShowDialog will create it's own message loop for the thread (blocking the main message loop if there is one). In this case, there is no already running message loop on your secondform thread, so nothing will block.
private void StartForm2()
{
TextString = txtChangeCase.Text;
secondForm = new Form2();
//Application.Run(secondForm);
secondForm.ShowDialog();
if (txtChangeCase.Text != TextString)
{
BeginInvoke(updatedtextdelegate, null);
}
}

Personally, I prefer to put all your forms into a single thread. That way, there is no cross-thread mayhem to deal with.
Then put your workers into separate threads.
See Link (http://www.chumpusrex.com/junk/Test1.rar)

I just tried the showDialog option and it worked. This surprised me is that before it just the form appeared and disappeared instantly in another thread, or with a regular showdialog with would block the first form and button1.

However, I still cannot get form2 to go to the front if it is already open. I get an exception caused by the invalid invocation. I also cannot get it to work with show because of the threading error.

My end goal is to have a way to have one main thread run all the visual items, I just don't know how to do it.

I don't know the best way to do what I need, which is what this post is about. Here are the list of requirements I have.
1. Button1 can be pressed at any time. (is there a way to protect it such the compiler will throw an error if some condition can block the button?)
2. Form2 or the request form cannot slow down or crash the main app. (henche the second thread and app)
2 It would be nice if form2 did what it was supposed to, or update the test in this case.

Thanks again.

elkinm
08-30-2010, 09:16 AM
I am going through your code. The only problem with it that when a message box pops up either from not selecting an option or if the worker is already running, button1 is blocked. In this case with a worker, both button1 and the stop work button should be pressable at all times.
I should be able to pull the fire-alarm or stop the worker (which may be causing the fire).

Thanks again.

EDIT, since the message box is the big problem at the moment can it be launched in a new thread that is always at the top but without interfering with the main program.

Mark R
08-30-2010, 09:54 AM
EDIT, since the message box is the big problem at the moment can it be launched in a new thread that is always at the top but without interfering with the main program.

First: I've edited my post because I was talking BS. Your code was almost right, but I didn't see the problem initially. Just that the idea of having multiple message-loops seemed a very strange way to solve the problem (but I can confirm that it does work). You need to fix your Invoke command (as I describe in the edited post).

The thing about a MessageBox is that it blocks the thread that it is running in. It is designed this way, so that the user can be informed of a problem that is stopping the program from continuing.

If you need an alert that doesn't block the thread - then you can just spawn a new form. Make a form that looks like a message box. Then just 'Show' it. It will run quite happily in the same thread as your main Form. This avoids any complicated cross-thread communication.

You could run a messagebox in another thread - but why add the complexity of another thread, when you can just use another form with an OK button and a Label in it.
1. Button1 can be pressed at any time. (is there a way to protect it such the compiler will throw an error if some condition can block the button?)
2. Form2 or the request form cannot slow down or crash the main app. (henche the second thread and app)
2 It would be nice if form2 did what it was supposed to, or update the test in this case.

1. The compiler won't give you an error if something can block the form - because it can't know. However, you have to be careful not to do anything that can block it.
MessageBox, ShowDialog, etc. will all block a thread. So will any long operation. So all these need to be avoided in the thread that runs your main form.
2. You can run the second Form and its Application in a new thread - but you have to get the invocations right.
3. The command to bring a window to the Front is Activate() not BringToFront(). Change your line to Activate, and it works right.

elkinm
08-30-2010, 10:22 AM
First: I've edited my post because I was talking BS. Your code was almost right, but I didn't see the problem initially. Just that the idea of having multiple message-loops seemed a very strange way to solve the problem (but I can confirm that it does work). You need to fix your Invoke command (as I describe in the edited post).

The thing about a MessageBox is that it blocks the thread that it is running in. It is designed this way, so that the user can be informed of a problem that is stopping the program from continuing.

If you need an alert that doesn't block the thread - then you can just spawn a new form. Make a form that looks like a message box. Then just 'Show' it. It will run quite happily in the same thread as your main Form. This avoids any complicated cross-thread communication.

You could run a messagebox in another thread - but why add the complexity of another thread, when you can just use another form with an OK button and a Label in it.


1. The compiler won't give you an error if something can block the form - because it can't know. However, you have to be careful not to do anything that can block it.
MessageBox, ShowDialog, etc. will all block a thread. So will any long operation. So all these need to be avoided in the thread that runs your main form.
2. You can run the second Form and its Application in a new thread - but you have to get the invocations right.
3. The command to bring a window to the Front is Activate() not BringToFront(). Change your line to Activate, and it works right.

That worked great, calling the invoke on form2 did the trick. I added a this.Activate() it went to the front just like you said. This is using the ShowDialog, not Application.run. When is bringtofront supposed to work?
I will try the application way and see if it works.
The only issue left right now is if I kill the second form it kills the application. This is the only reason where a second application for form2 is beneficial.

I don't need any message boxes, I am just trying to come up with things that could block button1 and try to protect it.

Thanks for all you help. I will try expanding on the program to make it more like my final project which will hopefully make it easier to understand my requirements.

elkinm
08-30-2010, 11:03 AM
I tried the Application.Run method and it worked, but there was still only one process so killing it still killed both forms, but that is not as important at the moment. I will work on expanding the application and post it as soon as I can.

Thanks again.

elkinm
08-30-2010, 04:19 PM
WARNING: the new application currently can run the main thread and 4 worker threads, which cripples my dual-core machine while it is running so please be careful running all the workers at once.

Here is the link: http://rapidshare.com/files/416108723/ThreadTest2.zip

Letís say that the application is a representation of a restaurant. I am the boss and I have 4 workers to do something. Working can be anything, taking orders, making sandwiches, waiting tables, ect. So I can see how much work each worker has done and I know how much total work has been completed.

Right now it is not perfect as the work counter restarts every time. I have not changed the worker process from your code yet. It would make more sense that each time I just give more work by increasing the work limit. (I know I am a bad boss)

Something that is not included yet is that all the workers should be aware of each other in the sense if one or several workers finish, they should help the other workers finish their work by taking some of the load. In code, lower the working limit and increase their limit and keep working. Also, there should be a break option, meaning that if a worker stops for a break, it should notify the other workers and they should work until it returns.
This is the easier case, the only problem is accurately checking the status of other workers.

There is another piece I have not included yet. There should be another data source that I technically cannot control which is my product provider.
This is a restaurant and to do work I need raw materials that I get from this external worker. For a sandwich I need 2 slices of bread, lettuce, pickles, tomato, ketchup and mustard, which is provided by other thread. The problem is that it is only one thread and it needs to supply products to all the threads.
Further more, I need to keep track of the produce I have available and when needed order more, and notify the workers if we are short some produce, to make less of the related products.
It really becomes an issue to not overload or overcall the supplying worker. All I technically need is one thread to be boss and handle the drawing, and one other thread between all the workers, assuming it makes it easier to work with the provider thread.

I know my explanation is not very clean and neither is my code. Hopefully it makes some sense though.

Please tell me what you think and if I can improve the current design.

I will try to enhance the application and try to better explain how it should run.

Thanks again.

Mark R
08-30-2010, 04:50 PM
There is another piece I have not included yet. There should be another data source that I technically cannot control which is my product provider.
This is a restaurant and to do work I need raw materials that I get from this external worker. For a sandwich I need 2 slices of bread, lettuce, pickles, tomato, ketchup and mustard, which is provided by other thread. The problem is that it is only one thread and it needs to supply products to all the threads.
Further more, I need to keep track of the produce I have available and when needed order more, and notify the workers if we are short some produce, to make less of the related products.
It really becomes an issue to not overload or overcall the supplying worker. All I technically need is one thread to be boss and handle the drawing, and one other thread between all the workers, assuming it makes it easier to work with the provider thread.

I'm not entirely clear what you mean. But it looks like you should consider using a ThreadPool to manage your workers.

The ThreadPool has a queue. You stick a job in the queue. The Threadpool gives it to the first available worker. If all the workers are busy, the job will wait in the queue until a worker gets to it. If the workers all stay busy then the ThreadPool will automatically create new workers to deal with the work. If there isn't enough work and the workers are idling too much, then it will start firing workers until it reaches an efficient state.

What it sounds like is that you want one master thread which essentially takes orders, and then feeds them to a ThreadPool which will then divide the orders up among the workers.

elkinm
08-30-2010, 10:52 PM
Sorry, I will try to clarify and add more to what should happen.

This being a restaurant, it is very important for how much I can get the supplies and how much I can sell the products.

So as the data source, lets say I have 1 PC with a display of every one of my supplies that I can buy for different prices and in different quantities. Lets say for one store I can buy bread 1 slice at a time, while another 2 slices and another 3 slices at a time. The more slices may be cheaper per slice, but I risk throwing away slices and loosing money.

Anyway, I at the start look at all the product sources and create tables for every combination to get to a needed sandwich. So lest say 1 sandwich takes 2 slices of bread, 1 slice of cheese, 1 leaf of lettuce, 3 slices of pickles, 2 squirts or ketchup and 3 squirts of mustard. So if I get 1 slice at a time I need to get 2 of these and buy everything else for the sandwich. If 2 at a time it is enough for a sandwich, and if it is 3 at a time, if I buy 2 3 at-a-times for 2 sandwiches. I also don't want to over-buy, as I might not sell all the sandwiches at the price I want.

So lets say I have one worker sitting at the computer monitoring all the supplier prices, and then I have a worker for each product source. Basically the one at the PC simply tells the handler that the price has changed. The guy gets updates from all the other condiment handlers of their prices and when it is updated sends it's new price to all the other condiments who need it as an event. As a result, all the supply handlers know how much all the other products cost without having to ask each one how much it costs. Also, only the product handler gets updates from the one guy who is at the computer.

So the lets say the 1 slice bread guy can get a slice for 50 cents each, but needs 2 for 1 dollar total, and it needs to buy a slice of cheese which it knows from the cheese guy costs 50 c each and a sheet of lettuce for another 50 cents for a total sandwich cost of 2 dollars. And it knows it can sell this sandwich for 2 dollars to break even.
So lets say I can all of a sudden I can get a slice for 40 cents each. If everything remains the same, I instantly make 20 cents per sandwich. I can even pay extra for the cheese or lettuce or even sell the sandwich for less and still make a profit.

Now, all buys have to go though the same PC as the data comes though, hence the single data thread. So if I need to buy more products I have to do it in a thread safe way. This can also cause a delay. Imagine a lunch rush were all prices go up so if I buy one product and miss the price on another I can loose money.

So in my code each one of the User control instances is it's own product source which gets data and notifies all it's partners of it's changes. So each individual piece knows what price it should try to buy to make a profit.

This can just as easily be adapted to buying a computer, you look for how much you can get a CPU, motherboard, ram, ect. and sometimes you can get bundles which may be cheaper, but possibly not as good.

I am not sure that a thread-pool is the right way to go since all the worker threads should always be running and waiting for new price updates and chances to buy. The code also depends on the price changes to usually occur much slower than the internal processing capability. So if one price updates, if should have time to notify the handler of the new price and it can notify his partners of the new price and he and all the partners can decide if they want to buy or not. However, it is very important that no 2 partners have different prices. I don't want one think it can buy bread at 40 cents a slice and another think it will buy for 50 cents per slice as this might result in inconsistent purchase actions.

Also, only the guy at the PC is aware of how to get prices or how to buy. The other threads only know that they can buy at some price, and only one piece of the thread is even aware of the guy at the PC to tell him to buy something.

Sorry, I know this is another very long explanation. This should be a much clearer example of what I want my program to do.

Thanks again.

elkinm
09-14-2010, 08:56 AM
Hi Again,

I still don't know how to make my full threaded program, but now I have a different need.

I need to create some kind of Audit Trail window that will show any important messages to the user. This is similar to logging, (which I also don't have yet) but only for select messages.

What I want is a new form with a DataGridview which will show status updates from the code.

If based on the threading application from before, I would like a time-stamp and a short description of what happened added in a new line.
An example would be buttto1 clicked, then button2 clicked, then worker1 started, worker2 started and so on.

Where threading comes in, I want the code to maintain all the changes in memory in a separate thread such that any part of the code can send a quick message to it and continue.
This second form does not need to be visible, but if it is launched it would show any events up to that point and keep updating when needed.

This seems very simple, just keep a table in memory and show form3 when needed with a binding to the table. The problem I am having is maintaining the new thread without the form running. I will see what I can get and post my solution.

Thanks

elkinm
09-15-2010, 09:18 PM
Here is my latest test version:
http://www.multiupload.com/6B7WCY5QW2

This is the same as the application from before with another form and button.

I am surprised it works at all, and I know it is not clean.

My biggest concern is architecture, not the code itself.

I create a table as part of the new form thread. Is there any need to do that? I bind the data grid in the form to this table.

I thought I would need to invoke the new thread to add the log entry.

The log window is intender for a very limited number of lines, but theoretically I would like it to handle a new line with every iteration of the worker threads.
That may very well lock the log window thread so I should be able to close the new form without killing the entire application.

Also, since the datagrid is virtual, does that mean it would not hurt performance much since new rows are not drawn?

I donít think my approach is any good and certainly not clean. However is some the architecture sound, or at least simple to improve?

Thanks again.