Link to home
Start Free TrialLog in
Avatar of ssteeves
ssteeves

asked on

Help with a "Basic" C# thread

Hi,

I'm trying to write a very simple thread in C#.  I can get most of it working, but I can't get the thread to pass back information to the calling form as it runs.  I can't find a decent example of what I need.  If I could get a simple example, I could learn from it.  Here's what I'd like...very simple.

1 form.  It would contain 3 buttons ("cmdRun", "cmdPause", and "cmdResume") and 1 text box ("txtInfo").  
1 class containing a method "CreateFile" that would create and write 1,000,000 lines to a text file. (To ensure it takes a few seconds to run).

When the "cmdRun" button is clicked, it would run the "CreateFile" method in a thread.  As each line is written to the file (From the CreateFile Method), I would like to have the line number displayed in the text box on the main form. (So I would see it increment from 1 - 1,000,000.  This is the main part I'm stuck on).  

Also, at any time, I'd like to be able to click the "Pause" and resume buttons, and if possible, I'd like the location of the file to be created to be specified in the "cmdRun" button, not hard coded into my class.

I'll give a starting amount of 200 points for an example that does all of these things (Note:  I may have to ask a few questions until I'm sure I understand it).  Then, I may post a few follow up questions if I wish to "enhance" the project with a few extras, but I'll give separate points/questions for follow ups.

Good luck, and Thanks so much!  I've been stuck on this problem all week...

ssteeves



Avatar of NetworkArchitek
NetworkArchitek

You want a delegate that does a callback. Here's a good quick example, you want to do thread pooling:

http://www.codeproject.com/dotnet/multithread.asp
Avatar of ssteeves

ASKER

Thanks for the link, but I'd really prefer to have someone post the code for the above mentioned sample project.  I'll have an easier time to understand it in that context.  I wasn't able to make much sense of that code...

Increasing points to 250...
You need to use Control.Invoke method of Form to update the UI from Different thread.

Here is the example.

https://www.experts-exchange.com/questions/21215229/Displaying-progress-during-execution.html

Cheers
Jatinder
ASKER CERTIFIED SOLUTION
Avatar of basetew
basetew

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
basetew,

Thanks so much for taking the time to write that code for me.  I've looked at it briefly, and it looks impresive!  I should be able to learn lots from it.  My only concern is that your main method (threadRun) isn't located in a separate class.  I'm not sure how easy I'm going to find it to move that method into a class by myself, without an example.

I'm not sure if it matters where the class is located, but in my project I wish to right click on my project name in the solution explorer, and add a separate "Class File".  There, I plan to put the method that does the bulk of the work in my program.

Are you able to modify your above code to adapt to this slight change?

Thanks!!

ssteeves
This line:

workerThread = new System.Threading.Thread(new System.Threading.ThreadStart(threadRun));

Means the thread = function this.threadRun().

So you could change it to anything that is visible! Eg, myApp.DoLongTaskA();

Or.. just bung the call to the real hard work inside my threadRun..

Any code running on this thread wanting to do a Form call should pipe it through enqueueWork(string,object) instead. The processQueueOnGuiThread then picks this up, and does it (on GUI thread). During debugging I often put this code at top of functions to ensure I'm calling GUI threads ok. Remember in XP calling GUI from a thread works, but crashes 2000 randomly, and 98 very quickly.

Ask if you'd like a more advanced version of the enqueueWork, which accepts a delegate and object-array instead. That way you can call any function in your app, no matter what it's protection level (eg, private/public), you would call it like this: enqueueWork(new myBlahFunctionDelegate(myFunctionExecuter), new object[]{true}); //would execute the function myFunctionExecuter(true) on the GUI thread.

Please note calling a GUI thread is different to calling a non-GUI thread. As a non-GUI thread doesn't have a .Invoke or .BeginInvoke to signal it.
Sorry, my advice:

> This line:
> workerThread = new System.Threading.Thread(new System.Threading.ThreadStart(threadRun));
> Means the thread = function this.threadRun().
> So you could change it to anything that is visible! Eg, myApp.DoLongTaskA();
> Or.. just bung the call to the real hard work inside my threadRun..

is wrong. Your worker thread wants to communicate with gui thread. My advice was for a gui thread communicating with the worker thread. The rest of the advice is correct.

To move threadRun() into your own call, simply modify this line:

private void enqueueWork(string code, object data)

to this:

public void enqueueWork(string code, object data) //TODO: refactor 'enqueueWork' to 'EnqueueWork'

Then inside your real threadRun, just get the object for the Form instance, and call the enqueueWork to do a "gui thing"

Don't forget you can add extra jobCode's by extending my if() statement to check for other jobCode strings.