This is a discussion on Threading in C# .Net 2005 : within the C# Programming forums, part of the Software Development category; Hi Sathish... Let’s say, in the example above, we wanted to better distinguish the output from each thread, perhaps ...
| |||||||
| Register | FAQ | Members List | Calendar | Mark Forums Read |
| |||
| Hi Sathish... Let’s say, in the example above, we wanted to better distinguish the output from each thread, perhaps by having one of the threads write in upper case. We could achieve this by passing a flag to the Go method: but then we couldn’t use the ThreadStart delegate because it doesn’t accept arguments. Fortunately, the .NET framework defines another version of the delegate called ParameterizedThreadStart, which accepts a single object argument as follows: public delegate void ParameterizedThreadStart (object obj); The previous example then looks like this: class ThreadTest { static void Main() { Thread t = new Thread (Go); t.Start (true); // == Go (true) Go (false); } static void Go (object upperCase) { bool upper = (bool) upperCase; Console.WriteLine (upper ? "HELLO!" : "hello!"); } hello! HELLO! In this example, the compiler automatically infers a ParameterizedThreadStart delegate because the Go method accepts a single object argument. We could just as well have written: Thread t = new Thread (new ParameterizedThreadStart (Go)); t.Start (true); A feature of using ParameterizedThreadStart is that we must cast the object argument to the desired type (in this case bool) before use. Also, there is only a single-argument version of this delegate. An alternative is to use an anonymous method to call an ordinary method as follows: static void Main() { Thread t = new Thread (delegate() { WriteText ("Hello"); }); t.Start(); } static void WriteText (string text) { Console.WriteLine (text); } The advantage is that the target method (in this case WriteText) can accept any number of arguments, and no casting is required. However one must take into account the outer-variable semantics of anonymous methods, as is apparent in the following example: 9 static void Main() { string text = "Before"; Thread t = new Thread (delegate() { WriteText (text); }); text = "After"; t.Start(); } static void WriteText (string text) { Console.WriteLine (text); } After Another common system for passing data to a thread is by giving Thread an instance method rather than a static method. The instance object’s properties can then tell the thread what to do, as in the following rewrite of the original example: class ThreadTest { bool upper; static void Main() { ThreadTest instance1 = new ThreadTest(); instance1.upper = true; Thread t = new Thread (instance1.Go); t.Start(); ThreadTest instance2 = new ThreadTest(); instance2.Go(); // Main thread – runs with upper=false } void Go() { Console.WriteLine (upper ? "HELLO!" : "hello!"); } thnx... |
| Sponsored Links |
| |||
| Hi Sathish... A thread can be named via its Name property. This is of great benefit in debugging: as well as being able to Console.WriteLine a thread’s name, Microsoft Visual Studio picks up a thread’s name and displays it in the Debug Location toolbar. A thread’s name can be set at any time – but only once – attempts to subsequently change it will throw an exception. The application’s main thread can also be assigned a name – in the following example the main thread is accessed via the CurrentThread static property: thnx... |
| |||
| Hi Deeban, what are Foreground and Background Threads.. how can i identify weather the thread is foreground thread or background.... thanks...
__________________ Sathish Kumar.R ![]() Knowledge is meant to SHARE |
| |||
| Hi Sathish.... By default, threads are foreground threads, meaning they keep the application alive for as long as any one of them is running. C# also supports background threads, which don’t keep the application alive on their own – terminating immediately once all foreground threads have ended. A thread's IsBackground property controls its background status, as in the following example: class PriorityTest { static void Main (string[] args) { Thread worker = new Thread (delegate() { Console.ReadLine(); }); if (args.Length > 0) worker.IsBackground = true; worker.Start(); } } If the program is called with no arguments, the worker thread runs in its default foreground mode, and will wait on the ReadLine statement, waiting for the user to hit Enter. Meanwhile, the main thread exits, but the application keeps running because a foreground thread is still alive. If on the other hand an argument is passed to Main(), the worker is assigned background status, and the program exits almost immediately as the main thread ends – terminating the ReadLine. When a background thread terminates in this manner, any finally blocks are circumvented. As circumventing finally code is generally undesirable, it's good practice to explicitly wait for any background worker threads to finish before exiting an application – perhaps with a timeout (this is achieved by calling Thread.Join). If for some reason a renegade worker thread never finishes, one can then attempt to abort it, and if that fails, abandon the thread, allowing it to die with the process (logging the conundrum at this stage would also make sense!) Having worker threads as background threads can then beneficial, for the very reason that it's always possible to have the last say when it comes to ending the application. Consider the alternative – foreground thread that won't die – preventing the application from exiting. An Changing a thread from foreground to background doesn’t change its priority or status within the CPU scheduler in any way. 11 abandoned foreground worker thread is particularly insidious with a Windows Forms application, because the application will appear to exit when the main thread ends (at least to the user) but its process will remain running. In the Windows Task Manager, it will have disappeared from the Applications tab, although its executable filename still be visible in the Processes tab. Unless the user explicitly locates and ends the task, it will continue to consume resources and perhaps prevent a new instance of the application from starting or functioning properly. thnx... |
| |||
| Hi Sathish... A thread’s Priority property determines how much execution time it gets relative to other active threads in the same process, on the following scale: enum ThreadPriority { Lowest, BelowNormal, Normal, AboveNormal, Highest } This becomes relevant only when multiple threads are simultaneously active. Setting a thread’s priority to high doesn’t mean it can perform real-time work, because it’s still limited by the application’s process priority. To perform real-time work, the Process class in System.Diagnostics must also be used to elevate the process priority as follows (I didn't tell you how to do this): Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High; ProcessPriorityClass.High is actually one notch short of the highest process priority: Realtime. Setting one's process priority to Realtime instructs the operating system that you never want your process to be preempted. If your program enters an accidental infinite loop you can expect even the operating system to be locked out. Nothing short of the power button will rescue you! For this reason, High is generally considered the highest usable process priority. If the real-time application has a user interface, it can be undesirable to elevate the process priority because screen updates will be given excessive CPU time – slowing the entire computer, particularly if the UI is complex. (Although at the time of writing, the Internet telephony program Skype gets away with doing just this, perhaps because its UI is fairly simple). Lowering the main thread’s priority – in conjunction with raising the process’s priority – ensures the real-time thread doesn’t get preempted by screen redraws, but doesn’t prevent the computer from slowing, because the operating system will still allocate excessive CPU to the process as a whole. The ideal solution is to have the real-time work and user interface in separate processes (with different priorities), communicating via Remoting or shared memory. Shared memory requires P/Invoking the Win32 API (web-search CreateFileMapping and MapViewOfFile). thanks... |
| |||
| Hi Deeban, How can i handle exception in threading... what are the exceptions rised while working with threading... thanks..
__________________ Sathish Kumar.R ![]() Knowledge is meant to SHARE |
| |||
| Hi Sathish... Any try/catch/finally blocks in scope when a thread is created are of no relevance once the thread starts executing. Consider the following program: public static void Main() { try { new Thread (Go).Start(); } catch (Exception ex) { // We'll never get here! Console.WriteLine ("Exception!"); } static void Go() { throw null; } } The try/catch statement in this example is effectively useless, and the newly created thread will be encumbered with an unhandled NullReferenceException. This behavior makes sense when you consider a thread has an independent execution path. The remedy is for thread entry methods to have their own exception handlers: public static void Main() { new Thread (Go).Start(); } static void Go() { try { ... throw null; // this exception will get caught below ... } catch (Exception ex) { Typically log the exception, and/or signal another thread that we've come unstuck ... } From .NET 2.0 onwards, an unhandled exception on any thread shuts down the whole application, meaning ignoring the exception is generally not an option. Hence a try/catch block is required in every thread entry method – at least in production applications – in order to avoid unwanted application shutdown in case of an unhandled exception. This can be somewhat cumbersome – particularly for Windows Forms programmers, who commonly use the "global" exception handler, as follows: 13 using System; using System.Threading; using System.Windows.Forms; static class Program { static void Main() { Application.ThreadException += HandleError; Application.Run (new MainForm()); } static void HandleError (object sender, ThreadExceptionEventArgs e) { Log exception, then either exit the app or continue... } } The Application.ThreadException event fires when an exception is thrown from code that was ultimately called as a result of a Windows message (for example, a keyboard, mouse or "paint" message) – in short, nearly all code in a typical Windows Forms application. While this works perfectly, it lulls one into a false sense of security – that all exceptions will be caught by the central exception handler. Exceptions thrown on worker threads are a good example of exceptions not caught by Application.ThreadException (the code inside the Main method is another – including the main form's constructor, which executes before the Windows message loop begins). The .NET framework provides a lower-level event for global exception handling: AppDomain.UnhandledException. This event fires when there's an unhandled exception in any thread, and in any type of application (with or without a user interface). However, while it offers a good last-resort mechanism for logging untrapped exceptions, it provides no means of preventing the application from shutting down – and no means to suppress the .NET unhandled exception dialog. thnx.. |
| |||
| Hi Sathish... When a thread waits or pauses as a result of using the constructs listed in the tables above, it's said to be blocked. Once blocked, a thread immediately relinquishes its allocation of CPU time, adds WaitSleepJoin to its ThreadState property, and doesn’t get re-scheduled until unblocked. Unblocking happens in one of four ways (the computer's power button doesn't count!): · by the blocking condition being satisfied · by the operation timing out (if a timeout is specified) · by being interrupted via Thread.Interrupt · by being aborted via Thread.Abort A thread is not deemed blocked if its execution is paused via the (deprecated) Suspend method. thnx... |
| |||
| Hi Deeban, what is Sleeping and Spinning, can you explain me with an example and when the Sleeping and Spinning are used.. thanks...
__________________ Sathish Kumar.R ![]() Knowledge is meant to SHARE |
| |||
| Hi Sathish... Calling Thread.Sleep blocks the current thread for the given time period (or until interrupted): static void Main() { Thread.Sleep (0); // relinquish CPU time-slice Thread.Sleep (1000); // sleep for 1000 milliseconds Thread.Sleep (TimeSpan.FromHours (1)); // sleep for 1 hour Thread.Sleep (Timeout.Infinite); // sleep until interrupted } More precisely, Thread.Sleep relinquishes the CPU, requesting that the thread is not rescheduled until the given time period has elapsed. Thread.Sleep(0) relinquishes the CPU just long enough to allow any other active threads present in a time-slicing queue (should there be one) to be executed. The Thread class also provides a SpinWait method, which doesn’t relinquish any CPU time, instead looping the CPU – keeping it “uselessly busy” for the given number of iterations. 50 iterations might equate to a pause of around a microsecond, although this depends on CPU speed and load. Technically, SpinWait is not a blocking method: a spin-waiting thread does not have a ThreadState of WaitSleepJoin and can’t be prematurely Interrupted by another thread. SpinWait is rarely used – its primary purpose being to wait on a resource that’s expected to be ready very soon (inside maybe a microsecond) without calling Sleep and wasting CPU time by forcing a thread change. However this technique is advantageous only on multi-processor computers: on single-processor computers, there’s no opportunity for a resource’s status to change until the spinning thread ends its time-slice – which defeats the purpose of spinning to begin with. And calling SpinWait often or for long periods of time itself is wasteful on CPU time. i hope this will help you... thnx... |
| |||
| Hi Deeban, can you explain with an example for, what is the difference between Blocking and Spinning? thanks..
__________________ Sathish Kumar.R ![]() Knowledge is meant to SHARE |
| |||
| Hi Sathish... A thread can wait for a certain condition by explicitly spinning using a polling loop, for example: while (!proceed); or: while (DateTime.Now < nextStartTime); This is very wasteful on CPU time: as far as the CLR and operating system is concerned, the thread is performing an important calculation, and so gets allocated resources accordingly! A thread looping in this state is not counted as blocked, unlike a thread waiting on an EventWaitHandle (the construct usually employed for such signaling tasks). A variation that's sometimes used is a hybrid between blocking and spinning: while (!proceed) Thread.Sleep (x); // "Spin-Sleeping!" The larger x, the more CPU-efficient this is; the trade-off being in increased latency. Anything above 20ms incurs a negligible overhead – unless the condition in the while-loop is particularly complex. Except for the slight latency, this combination of spinning and sleeping can work quite well (subject to concurrency issues on the proceed flag, discussed in Part 4). Perhaps its biggest use is when a programmer has given up on getting a more complex signaling construct to work! thnx... |
| |||
| Hi Deeban, How cann i join a thread with another thread... ? can you explain me with an example... thanks..
__________________ Sathish Kumar.R ![]() Knowledge is meant to SHARE |
| |||
| Hi Sathish.... You can block until another thread ends by calling Join: class JoinDemo { static void Main() { Thread t = new Thread (delegate() { Console.ReadLine(); }); t.Start(); t.Join(); // Wait until thread t finishes Console.WriteLine ("Thread t's ReadLine complete!"); } } The Join method also accepts a timeout argument – in milliseconds, or as a TimeSpan, returning false if the Join timed out rather than found the end of the thread. Join with a timeout functions rather like Sleep – in fact the following two lines of code are almost identical: Thread.Sleep (1000); Thread.CurrentThread.Join (1000); 17 (Their difference is apparent only in single-threaded apartment applications with COM interoperability, and stems from the subtleties in Windows message pumping semantics described previously: Join keeps message pumping alive while blocked; Sleep suspends message pumping). thnx... |
| |||
| Hi Deeban, can you explain, what is Locking and Thread Safety in threading in dot net...? thanks...
__________________ Sathish Kumar.R ![]() Knowledge is meant to SHARE |
| |||
| Hi Sathish... Locking enforces exclusive access, and is used to ensure only one thread can enter particular sections of code at a time. For example, consider following class: class ThreadUnsafe { static int val1, val2; static void Go() { if (val2 != 0) Console.WriteLine (val1 / val2); val2 = 0; } } This is not thread-safe: if Go was called by two threads simultaneously it would be possible to get a division by zero error – because val2 could be set to zero in one thread right as the other thread was in between executing the if statement and Console.WriteLine. Here’s how lock can fix the problem: class ThreadSafe { static object locker = new object(); static int val1, val2; static void Go() { lock (locker) { if (val2 != 0) Console.WriteLine (val1 / val2); val2 = 0; } } } Only one thread can lock the synchronizing object (in this case locker) at a time, and any contending threads are blocked until the lock is released. If more than one thread contends the lock, they are queued – on a “ready queue” and granted the lock on a first-come, first-served basis as it becomes available. Exclusive locks are sometimes said to enforce serialized access to whatever's protected by the lock, because one thread's access cannot overlap with that of another. In this case, we're protecting the logic inside the Go method, as well as the fields val1 and val2. A thread blocked while awaiting a contended lock has a ThreadState of WaitSleepJoin. Later we discuss how a thread blocked in this state can be forcibly released via another thread calling its Interrupt or Abort method. This is a fairly heavy-duty technique that might typically be used in ending a worker thread. C#’s lock statement is in fact a syntactic shortcut for a call to the methods Monitor.Enter and Monitor.Leave, within a try-finally block. Here’s what’s actually happening within the Go method of the previous example: try { Monitor.Enter (locker); if (val2 != 0) Console.WriteLine (val1 / val2); val2 = 0; } finally { Monitor.Exit (locker); } Calling Monitor.Exit without first calling Monitor.Enter on the same object throws an exception. Monitor also provides a TryEnter method allows a timeout to be specified – either in milliseconds or as a TimeSpan. The method then returns true – if a lock was obtained – or false – if no lock was obtained because the method timed out. TryEnter can also be called with no argument, which "tests" the lock, timing out immediately if the lock can’t be obtained right away. thanks... |