Threading How to

A

Andy Williams

Apologies in advance for the long post.

I have an application which has 2 CheckedListBox controls, CLB 1 is a list
of Directories and CLB 2 is a list of Files.

Directories can be added to CLB 1 by clicking an Add button.

Users can Check Directories in CLB 1 and the app then populates CLB2 with a
list of Files in the Checked Directories. In some cases there can be a large
number of files in the directories so it can take a long time to populate CLB
2 and whilst this population takes place the app hangs.

So, I've started to look at threading. I've managed to create a Finder Class
that is started as a thread on the Item_Click event of CLB1. This seems to
work OK in that it allows the app to continue to repond to user input e.g.
clicking the Add button or Checking an item in CLB1. The problem is that I
need to suspend or in some cases cancel the Finder thread depending on what
the users does. For example if the User clicks Directory 1 it is Checked and
the Finder goes off and finds the files in Directory 1 and adds them 2 CLB 2.
However if, whilst the Finder is still running the User clicks Directory 1
again then it is Unchecked and we need to remove all the files from Directory
1 from the CLB 2 but because the Finder is running it will keep adding files
it hasn't yet found unless it is stopped.

I need to know how to Suspend or Cancel the Finder thread without using
deprecated commands such as Suspend or Stop
 
C

Cor Ligthert [MVP]

Andy,

As you needs stops, then you first have to ask yourself, why am I using
threads?

Keep in mind that every thread cost your more processing time than withouth
extra threads.
The only advance you can have is the througput time.

Cor
 
B

Brian Gideon

Apologies in advance for the long post.

I have an application which has 2 CheckedListBox controls, CLB 1 is a list
of Directories and CLB 2 is a list of Files.

Directories can be added to CLB 1 by clicking an Add button.

Users can Check Directories in CLB 1 and the app then populates CLB2 witha
list of Files in the Checked Directories. In some cases there can be a large
number of files in the directories so it can take a long time to populateCLB
2 and whilst this population takes place the app hangs.

So, I've started to look at threading. I've managed to create a Finder Class
that is started as a thread on the Item_Click event of CLB1. This seems to
work OK in that it allows the app to continue to repond to user input e.g..
clicking the Add button or Checking an item in CLB1. The problem is that I
need to suspend or in some cases cancel the Finder thread depending on what
the users does. For example if the User clicks Directory 1 it is Checked and
the Finder goes off and finds the files in Directory 1 and adds them 2 CLB 2.
However if, whilst the Finder is still running the User clicks Directory 1
again then it is Unchecked and we need to remove all the files from Directory
1 from the CLB 2 but because the Finder is running it will keep adding files
it hasn't yet found unless it is stopped.

I need to know how to Suspend or Cancel the Finder thread without using
deprecated commands such as Suspend or Stop

What you probably need here is a dedicated worker thread for doing
this task. You will spin up the thread when the application starts
(or possibly use a more lazy initialization approach) and leave it
running...permanently. When you want it to perform a task send a
message to it. The thread should send a message back to the UI thread
when it is complete.

A good way to send a message to the worker thread is to have it wait
on a WaitHandle (ManualResetEvent or AutoResetEvent) which triggers it
to wake up and perform work. Maybe the UI thread sets a few variables
or some other data structure prior to "setting" the WaitHandle which
the worker thread reads and uses to know what work to perform. After
the worker thread has completed its work and informed the UI thread
then it wait again on the same WaitHandle. That's typically
accomplished by placing and infinite loop inside the entry point of
the thread.

The worker thread should call ISynchronizeInvoke.Invoke (available on
a Control or Form) when it needs to send the result back to the UI
thread. Remember, you can never access a Form or Control from
anything other than the UI thread. Even just reading values from them
is an unsafe operation.

To cancel an operation in progress use Michael suggestions.
 
C

Cor Ligthert[MVP]

As I have read the last answer before this in this message thread.

In my idea are handles that are from the time before .Net.

Working with threads are easy to do as you use a Queue or a Generic queue

http://msdn.microsoft.com/en-us/library/7977ey2c(VS.80).aspx

You have to synclock it simple as you enque something and as you dequeu
something.

Never let a process loop infinity, that is seriously putting the horse
behind the car (and then even in the wrong direction).

Cor
 
B

Brian Gideon

As I have read the last answer before this in this message thread.

In my idea are handles that are from the time before .Net.

I was referring to the WaitHandle subclasses that have been in
the .NET BCL since version 1. They are a fundamental part of
threading solutions and architectures.
Working with threads are easy to do as you use a Queue or a Generic queue

http://msdn.microsoft.com/en-us/library/7977ey2c(VS.80).aspx

You have to synclock it simple as you enque something and as you dequeu
something.

I actually agree that some use of a queue could be helpful to the OP.
But it isn't quite as simple as using the builtin Queue class. How
would the worker thread know that an item arrived in the queue? A
better option would be to use a blocking queue which is not available
in the BCL nor is it trivia to write.
Never let a process loop infinity, that is seriously putting the horse
behind the car (and then even in the wrong direction).

Stange. Because that is *exactly* what every windows forms application
does when it starts. What do you think Application.Run is doing? How
do you propose to keep a thread running indefinitely without using a
loop?
 
C

Cor Ligthert[MVP]

Brian,

I did not want to make it to difficult in my reply.

But normally the thread will end as the queue is empty.

So testing on that before you you enque something and start the tread is a
very simple action. And is like I use it.

Application.run is activating the message pump

Cor

"Brian Gideon" <[email protected]> schreef in bericht
As I have read the last answer before this in this message thread.

In my idea are handles that are from the time before .Net.

I was referring to the WaitHandle subclasses that have been in
the .NET BCL since version 1. They are a fundamental part of
threading solutions and architectures.
Working with threads are easy to do as you use a Queue or a Generic queue

http://msdn.microsoft.com/en-us/library/7977ey2c(VS.80).aspx

You have to synclock it simple as you enque something and as you dequeu
something.

I actually agree that some use of a queue could be helpful to the OP.
But it isn't quite as simple as using the builtin Queue class. How
would the worker thread know that an item arrived in the queue? A
better option would be to use a blocking queue which is not available
in the BCL nor is it trivia to write.
Never let a process loop infinity, that is seriously putting the horse
behind the car (and then even in the wrong direction).

Stange. Because that is *exactly* what every windows forms application
does when it starts. What do you think Application.Run is doing? How
do you propose to keep a thread running indefinitely without using a
loop?
 
B

Brian Gideon

Brian,

I did not want to make it to difficult in my reply.

But normally the thread will end as the queue is empty.

So testing on that before you you enque something and start the tread is a
very simple action. And is like I use it.

Sure, but then you might have to initialize a new thread for each
operation. Which is not to say that's a bad approach especially if
these operations only need to be performed infrequently. Personally,
I just lean more toward the dedicate thread approach because it allows
you to extend it's basic behavior into something more advanced like
prefetching the contents of a directory that hasn't even been selected
yet.
Application.run is activating the message pump

....which executes an infinite loop waiting on a wait handle to notify
it when a new message has arrived.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top