Intra-Thread communication

  • Thread starter Thread starter Just Tom
  • Start date Start date
J

Just Tom

I have a Winform that will spawn a thread to work on each file within a
directory. For each FileSystemInfo in this directory, it will get the hash
of that file. If the FileSystemInfo is infact another directory, I will
spawn another thread and repeat the whole process. However I want to keep
track of which directory is being parsed, so I want to list this in a Text
box back in the Winform. Here is my problem.

How do I get a thread to communicate back to the Winform the directory that
it is operating upon? The thread knows nothing about the form's class as
the thread is not instantiating that class. Everything I have tried so far
does not work.

Can somebody point me in the right direction?
 
Why don't you pass the form's instance to the thread?
Also, note, that windows controls should be only accessed from within UI
thread, thus you'll need Invoke method of form.
 
Just Tom said:
I have a Winform that will spawn a thread to work on each file within a
directory. For each FileSystemInfo in this directory, it will get the hash
of that file. If the FileSystemInfo is infact another directory, I will
spawn another thread and repeat the whole process. However I want to keep
track of which directory is being parsed, so I want to list this in a Text
box back in the Winform. Here is my problem.

This is a very stupid approach. If the directory has 2000 files, you wil
lspwan 2000 threads. This is ridiculous. Blows tons of memory and will slow
your computer to a halt.

You should not never ever span a thread for this. Either spawn ONE other
thread for this (working off a list there), or spawn a number of threads
(or, being smart, use the ThreadPool that .NET handles and post work items).

Keeping the number of threads under control (as in: relatively small, leT's
say 25 per processor maxium) is part of your performance target.

2000 threads (popssible, you could even end up with way more) will take
gigabytes of memory just for their stacks.
How do I get a thread to communicate back to the Winform the directory that
it is operating upon? The thread knows nothing about the form's class as
the thread is not instantiating that class. Everything I have tried so far
does not work.

* Why do you want the threads to communicate back the the winform DIRECTORY?
* They need to know thom to talk back to, and you ahve to pass this in as a
parameter. A Delegate to an Interface would suffice (that points to the
form, basically), but you have to pass in information on whom to call back.

Basically:

* Define the method that the threads call back to.
* Create a delegate to this method (implemented in the form)
* Pass the delegate to the thread as part of the start parameters.
* Voila.

But PLEASE, do NOT open threads as you do.
Can somebody point me in the right direction?

--
Regards

Thomas Tomiczek
THONA Software & Consulting Ltd.
(Microsoft MVP C#/.NET)
(CTO PowerNodes Ltd.)
 
I agree that it is superDuper stupid to spawn threads like this, it will kill the system if yo
point it at the wrong directory

My addon to the previous speaker is that you could use async-delegates to perfor
the work, then your application will spawn threads from the pool and keep the programming-mode
quite easy.
 
Thomas Tomiczek said:
This is a very stupid approach. If the directory has 2000 files, you wil
lspwan 2000 threads. This is ridiculous. Blows tons of memory and will slow
your computer to a halt.

You should not never ever span a thread for this. Either spawn ONE other
thread for this (working off a list there), or spawn a number of threads
(or, being smart, use the ThreadPool that .NET handles and post work items).

Keeping the number of threads under control (as in: relatively small, leT's
say 25 per processor maxium) is part of your performance target.

I plan to use each thread for the whole directory and this thread will
operate on every file within this directory. Like 5000+ files. ONLY if
there is a SUB-directory am I spawning a new thread. This new spawned
thread will then work on every file in the subdirectory (3k-6k) and again
only spawn another thread if there is a subdirectory within the
subdirectory, etc...

This will only spawn 45 threads at max. But more like 25.

2000 threads (popssible, you could even end up with way more) will take
gigabytes of memory just for their stacks.

Could I create a limiter like a semaphore to prevent more than a defined
number of threads? So that each new thread will stall until the number
threads is kept below, say 45? how does one do this in C#?

* Why do you want the threads to communicate back the the winform DIRECTORY?
* They need to know thom to talk back to, and you ahve to pass this in as a
parameter. A Delegate to an Interface would suffice (that points to the
form, basically), but you have to pass in information on whom to call back.

Basically:

* Define the method that the threads call back to.
* Create a delegate to this method (implemented in the form)
* Pass the delegate to the thread as part of the start parameters.
* Voila.

I will try this approach. Thanks!
 
Inline ***.
Willy.
Just Tom said:
I plan to use each thread for the whole directory and this thread will
operate on every file within this directory. Like 5000+ files. ONLY if
there is a SUB-directory am I spawning a new thread. This new spawned
thread will then work on every file in the subdirectory (3k-6k) and again
only spawn another thread if there is a subdirectory within the
subdirectory, etc...

This will only spawn 45 threads at max. But more like 25.
*** Which is still too much.
Could I create a limiter like a semaphore to prevent more than a defined
number of threads? So that each new thread will stall until the number
threads is kept below, say 45? how does one do this in C#?
*** Use a thread from the threadpool, by calling QueueUserWorkItem.
 
Hi Tom,

First I would suggest you against that many threads, if you do this process
on a directory like "Program Files" you can get poor results.

Anyway, regarding how to comunicate with the main form is very easy,
basically you create a delegate, a method with that signature and then from
the thread you use Control.Invoke of the delegate, where Control is a
control in the form. You only need the control to force the method to be
execute in the correct thread.

here is some code, I do a "similar" thing than you, I copy all the images
from a directory to another directory and rename them in the process. I
chopped the code but all you need is still there.

Cheers,

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation


// the delegate
public delegate void ProcessedFileHandler( );

//the needed variables
Thread workingThread;
ProcessedFileHandler procfilehandler;

//the controls.
private System.Windows.Forms.ProgressBar progressBar1;
private System.Windows.Forms.Label FileNameLBL;


//This goes in the Load event

procfilehandler = new ProcessedFileHandler( this.UpdateProgressBar);
//Start the thread
this.workingThread = new Thread( new ThreadStart( this.ExportImage ));
this.workingThread.Start();


//The worker method
void ExportImage( )
{
rapi = new RAPI();
rapi.Connect(true);

//pudate the variables, here I use a lock ( not shown )
lock( this.syslock)
{
this.currentpos++;
this.currentfile = Path.GetFileName(imageURL);
}
//Update the interface
this.progressBar1.Invoke( procfilehandler, null);

//All we need is a control in the main thread to execute a method on the
main thread.
//this is another delegate ( not shown ) it's needed for the UI to know
the process is over.
this.progressBar1.Invoke( new ProcessedFileHandler( this.Done), null);
}


//the handler
void UpdateProgressBar( )
{
this.progressBar1.Value++;
FileNameLBL.Text = currentfile;
currentLBL.Text = currentpos.ToString();
}
 
Back
Top