First of all, a handy tip - it looks like you pasted the code directly
from VS.NET into your mail client. For some reason, when sending mail
as plain text (and I *think* these listservs are set up always to send
as plain text) code always comes out looking wrong when you do this - it
gets double spaced and loses all its tabs, making it really hard for
anyone to read the code. (This in turn makes it hard for them to help
you.) So I always copy from VS.NET and past into Notepad, and then
recopy from Notepad and paste into the email client.
But now on to your actual questions:
> I have a situation, I am calling a method asynchronously, which
> does not return values. If I make 100 call asynchronously, will
> the performance go down?
Define 'performance' in this context. There isn't really a simple
answer to your question, but I can explain a little about what actually
happens when you do this, which I hope will enable you to work out what
the answer will be in your particular situation.
First, when you say you are calling a method asynchronously, do you mean
you're using asynchronous delegate invocation? Or one of the many other
forms of asynchrony supported in the .NET Framework? (E.g.
Control.BeginInvoke - that is implemented in a completely different
fashion from the BeginInvoke method supplied by all delegates.)
Looking through the code you posted, the only place I see any async is
here:
private void Form2_Load(object sender, System.EventArgs e)
{
mydelegate dl=new mydelegate(Form2_EventSubscribe);
dl.BeginInvoke(null,null);
}
So that would be asynchronous delegate invocation then.
In which case, here's what will happen when you make 100 calls. Each
time you call BeginInvoke on a delegate, the delegate queues up a work
item with the CLR thread pool. The thread pool has a work queue
associated with it, and the threads in the pool all retrieve items from
this queue and work on them.
So the first thing that will happen when you put 100 items in the queue
in quick succession is that the thread pool queue length will grow.
This in itself is not going to have a major impact on performance - it
just takes up some memory. (Although there will eventually come a point
where the thread pool will refuse to accept new work items.)
What happens next depends on three things: 1) how long each work item
takes to execute, 2) what proportion of the time those work items spend
using CPU cycles vs. waiting for something to happen, and 3) how many
CPUs you have.
If each item executes very quickly, then what will most likely happen is
that the thread pool will use the same thread to execute each item in
turn - so you might never see more than 1 thread pool thread being used.
But if they take longer (e.g. a couple of seconds) the thread pool will
consider changing its strategy. It might increase the number of
threads, although it will only do so if the threads are not CPU-bound.
If the CPU is 100% busy, it won't bother creating extra threads. If the
CPU seems to have significant idle time, it'll create more threads. But
it will never create more threads than 25*(number of CPUs in system)
unless you've taken steps to change from the default settings for the
threadpool.
What impact will this have on performance? Well, the single most
important factor will be the work you're doing asynchronously, which is
why it's not possible to say, in general, what the impact of putting 100
work items in the queue will be - it depends on the work in question.
If the work you're doing is expensive, then obviously it'll slow things
down. In the worst case, if all of these threads are performing IO
intensive work on the same device, you might get 25 threads all
simultaneously trying to use that device. (Or 50 threads on a dual
proc, etc...) But you won't see the system attempt to run all 100 items
at once. (Unless you have a 4 CPU box...)
Since the performance characteristics are heavily determined by what
you're actually doing on those threads, the only way to know for sure is
to try it out and see what happens.
> My understanding is - I can't use threadpool,
Actually you *are* using the threadpool. Calling BeginInvoke on a
delegate implicitly uses the threadpool. (Although there are serious
problems with your code, as I'll explain later. You shouldn't be using
the thread pool. But you shouldn't be creating other threads either.
The bulk of the code you're trying to run asynchronously will in fact
have to run on the UI thread... But that's just because of what you're
trying to do in the method you're calling asynchronously.)
> because FormA loads FormB and which inturn calls a method
> Asynchronously. FormA may load 100 FormB, but FormB will
> call the method only once per instance.
Why would that stop you using the threadpool?
First of all, bear in mind that with the code you posted, Form1 and
Form2 will both use the same UI thread. Form1 creates instances of
Form2 here:
private void button1_Click(object sender, System.EventArgs e)
{
Form2 frm2 = new Form2 ();
frm2.Show ();
}
That's a click handler, which will always run on the UI thread of Form1.
So you're creating instances of Form2 on Form1's UI thread.
So all 100 instances of Form2 will run on the same thread in your
program. This is normal, and does not stop you from using the thread
pool for async work.
> a. I don't have a need to call endinvoke, What will happen to that
> child thread, when it will die?
First of all you MUST call EndInvoke. It is simply not correct to say
that you "don't have a need to call endinvoke." If you call BeginInvoke
on a delegate you are *required* to call EndInvoke on it at some point.
So you do have a need - the need to call EndInvoke is a direct
consequence of calling BeginInvoke.
As for the second half of your question, I think you've misunderstood
how asynchronous delegate invocation works. In this part of your code:
mydelegate dl=new mydelegate(Form2_EventSubscribe);
dl.BeginInvoke(null,null);
this does not cause a thread to be created. It just queues up work with
the thread pool. This work will be handled by one of the threads in the
thread pool, a thread which will then go on to do other things. (That's
the whole point of a thread pool.) So the system doesn't create a
thread specially to deal with this BeginInvoke call. (In certain
circumstances, calling BeginInvoke can trigger the creation of a new
thread in the thread pool. But that thread will always outlive the work
that caused it to be created, and will usually go on to handle further
work items. So in short, there is not a 1 to 1 correspondance between
threads and calls to BeginInvoke.)
So, when will the thread that executed your async call die? Whenever
the thread pool decides it is time for that thread to die. This could
happen at any time - it might happen straight away, it might not happen
until the program exits. But since you don't own that thread, it's not
really useful for you to know when it exits. Thread pool threads are
not yours, they are merely loaned to you. If you're doing anything that
requires you to know when the thread dies, you probably shouldn't be
using the thread pool.
> b. How do I control the child thread, i.e. terminate the child
> thread created my the asycn call?
See above - you can't, and there was no thread created just for your
async call. The thread is owned by the thread pool, and is likely to
service many async requests in its lifetime.
If you have some need to manage the lifetime of the thread, you can't
use the threadpool. Which means you can't use asynchronous delegate
invocation. Create your own thread instead.
By the way, your code as posted is horribly broken, and you should never
write code that works like this. The problem is that the method you are
launching asynchronously attempts to do things with the UI. For
example, it contains code like this:
this.button1.Click += new System.EventHandler(this.button1_Click);
this.button2.Click += new System.EventHandler(this.button2_Click);
this.MouseDown += new
System.Windows.Forms.MouseEventHandler(this.Form2_MouseDown);
This violates the golden rule of multithreading in Windows Forms: you
must not use controls on any thread other than the thread on which they
were created. This code snippet breaks that rule on every line - you're
not allowed to subscribe to a control's events from any thread other
than the UI thread.
The documentation for the Control class makes it pretty clear that your
code isn't right - look at what it says under "Thread Safety":
" Only the following members are safe for multithreaded operations:
BeginInvoke, EndInvoke, Invoke, InvokeRequired, and CreateGraphics."
Those are the only exceptions to the golden rule. Note that it does not
say that members such as Click or MouseDown are safe for multithreaded
operations. So the only thread you can ever run code like this on is
the UI thread. (And by the way, it makes no difference whether you use
the thread pool or you create your own threads. It's all against the
rules because you have to use the UI thread.)
What's less immediately obvious from the docs is that controls have
thread affinity, i.e. it's not enough to do use locking primitives to
serialize access to them - you must use the same thread every time.
(This is made clear in the documentation for Control.InvokeRequired. It
would be nice if it were also made explicit in Thread Safety section of
the main page for Control.)
For more information on how to write multithreaded code there are a
number of articles you can look at (including one by me :) ) - Chris
Sells has compiled a list here:
http://www.sellsbrothers.com/news/showTopic.aspx?ixTopic=1707
--
Ian Griffiths - DevelopMentor
http://www.interact-sw.co.uk/iangblog/
> -----Original Message-----
> From: Sathiamurthy, Venkat
>
> I have a situation, I am calling a method asynchronously, which does
not
> return values. If I make 100 call asynchronously, will the performance
> go down?
>
> My understanding is - I can't use threadpool, because FormA loads
FormB
> and which inturn calls a method Asynchronously. FormA may load 100
> FormB, but FormB will call the method only once per instance.
>
> My additional questions are,
> a. I don't have a need to call endinvoke, What will happen to that
child
> thread, when it will die?
> b. How do I control the child thread, i.e. terminate the child thread
> created my the asycn call?
===================================
This list is hosted by DevelopMentor� http://www.develop.com
View archives and manage your subscription(s) at http://discuss.develop.com