My many Thanks to Ian Griffiths and Bob Lynch, Your comments and suggestions were very helpful.
Can you please explain me or refer article about Control.Invoke/Control.BeginInvoke and give me more insights about - When Control.InvokeRequired = true, calling this.BeginInvoke(new methoddelgate(function)) will call the control's properties using correct thread? Thanks, Venkat -----Original Message----- From: Unmoderated discussion of advanced .NET topics. [mailto:[EMAIL PROTECTED] On Behalf Of Ian Griffiths Sent: Thursday, February 24, 2005 6:19 AM To: [email protected] Subject: Re: [ADVANCED-DOTNET] Asynchronous call - Thread life 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(r) http://www.develop.com View archives and manage your subscription(s) at http://discuss.develop.com =================================== This list is hosted by DevelopMentor� http://www.develop.com View archives and manage your subscription(s) at http://discuss.develop.com
