GOTCHA 59 Threads invoked using delegates behave like background threads


GOTCHA #59 Threads invoked using delegates behave like background threads

If you want a method to be executed from another thread, you can create a thread, set it to background, and then start it. That is three lines of code at least, isn't it? What if your method takes parameters? That is even more work. This is where the Delegate class's BeginInvoke() and EndInvoke() methods look very enticing. Delegates provide BeginInvoke() and EndInvoke() to call a method asynchronously. The intended method is invoked from another thread, and the code is pretty easy to write.

Let's see how you can do just that in Example 7-16.

Example 7-16. Using Delegate to call methods in another thread

C# (BeginInvoke)

 using System; namespace DelegateThread {     class Test     {         private static void Method1(int val)         {             Console.Write("Method 1 called from Thread {0}",                 AppDomain.GetCurrentThreadId());             Console.WriteLine(" with value {0}", val);         }         delegate void Method1Delegate(int val);         [STAThread]         static void Main(string[] args)         {             // It is not so easy to call Method1 from             // another thread using the Thread class.             Method1Delegate dlg = new Method1Delegate(Method1);             dlg.BeginInvoke(2, null, null);             Console.ReadLine();         }     } } 

VB.NET (BeginInvoke)

 Module Test     Private Sub Method1(ByVal val As Integer)         Console.Write("Method 1 called from Thread {0}", _             AppDomain.GetCurrentThreadId())         Console.WriteLine(" with value {0}", val)     End Sub     Delegate Sub Method1Delegate(ByVal val As Integer)     Public Sub Main()         ' It is not so easy to call Method1 from         ' another thread using the Thread class.         Dim dlg As New Method1Delegate(AddressOf Method1)         dlg.BeginInvoke(2, Nothing, Nothing)         Console.ReadLine()     End Sub End Module 

In this example, you simply create an object of the delegate Method1Delegate and call its BeginInvoke() method, passing the desired value for its first argument. The two null/Nothing arguments indicate that you are not passing a callback method or AsyncState object. The output is shown in Figure 7-17.

Figure 7-17. Output from Example 7-16


If you are able to execute the method in another thread so easily, why would you do it any other way? Well, this is perfectly OK, but you need to understand the benefits and drawbacks:

  • The method is executed by a thread from the thread pool.

  • The method is executed by a thread that is marked as a background thread.

  • Exceptions thrown from the method are lost unless you call EndInvoke(), even for methods that do not return any results.

What do these considerations imply? Since you use a thread from the thread pool, its execution depends on the availability of a thread (see "Gotcha #58, "Threads from the thread pool are scarce). Since it is a background thread, it will be terminated if all foreground threads terminate (see Gotcha #49, "Foreground threads may prevent a program from terminating" and Gotcha #50, "Background threads don't terminate gracefully"). Also, since it is from the thread pool, any exceptions thrown in it are handled by the pool. As a result you may not even realize that an exception occurred until you call EndInvoke() (see Gotcha #61, "Exceptions thrown from threads in the pool are lost"). With a C# void method, or a VB.NET Sub, you normally have no reason to call EndInvoke(). But you have to if you want to know if the method completed successfully. Finally, you don't want to synchronize with any other threads while running in the context of a thread-pool thread. If you do, it may delay the start of other tasks that need a thread from the thread pool.

IN A NUTSHELL

Fully understand the behavior and limitations of using Delegate.BeginInvoke(). It has all the advantages and limitations of using a background thread and a thread from the thread pool.

SEE ALSO

Gotcha #49, "Foreground threads may prevent a program from terminating," Gotcha #50, "Background threads don't terminate gracefully," Gotcha #58, "Threads from the thread pool are scarce," and Gotcha #61, "Exceptions thrown from threads in the pool are lost."



    .NET Gotachas
    .NET Gotachas
    ISBN: N/A
    EAN: N/A
    Year: 2005
    Pages: 126

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net