Threading in .NET

本文详细阐述了进程与AppDomain的概念差异,重点介绍了如何使用线程和参数化线程启动方法,并通过AutoResetEvent和ManualResetEvent展示了线程同步机制的应用。此外,还探讨了Mutex的工作原理及其与锁和Monitor对象的不同之处。
AppDomain vs Process

 

  • Process有自己独立的内存和资源,一个process至少有一个thread;
  • Appdomain 是process中的一个逻辑概念,一个process中可以有多个AppDomain,一个AppDomain中可以有0个或者多个thread;

 

优点:

 

  • 当process需要访问彼此的data时,需要使用proxy,这样会引入额外的代码和开销;使用AppDomain,我们可以在一个process中 launch多个应用程序,thread可以跨domian执行而不引入额外的开销和通信;

 


 

 Starting Threads

  • Thread(ThreadStart)
  • Thread(ParameterizedThreadStart)

 

No Parameters

 

 

Thread workerThread = new Thread(StartThread);
Console.WriteLine("Main Thread Id {0}",
    Thread.CurrentThread.ManagedThreadId.ToString());
workerThread.Start();

....
....
public static void StartThread()
{
    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine("Thread value {0} running on Thread Id {1}",
            i.ToString(), 
            Thread.CurrentThread.ManagedThreadId.ToString());
    }
}

 

 

Single Parameter
//using parameter
Thread workerThread2 = new Thread(ParameterizedStartThread);
// the answer to life the universe and everything, 42 obviously
workerThread2.Start(42); 
Console.ReadLine();

....
....
public static void ParameterizedStartThread(object value)
{
    Console.WriteLine("Thread passed value {0} running on Thread Id {1}",
        value.ToString(),
        Thread.CurrentThread.ManagedThreadId.ToString());
}

 

Synchronization

 AutoResetEvent

 

From MSDN:

"A thread waits for a signal by calling WaitOne on the AutoResetEvent. If the AutoResetEvent is in the non-signaled state, the thread blocks, waiting for the thread that currently controls the resource to signal that the resource is available by calling Set.

Calling Set signals AutoResetEvent to release a waiting thread. AutoResetEvent remains signaled until a single waiting thread is released, and then automatically returns to the non-signaled state. If no threads are waiting, the state remains signaled indefinitely."

 

 

using System;
using System.Threading;

namespace AutoResetEventTest
{
    class Program
    {
        public static Thread T1;
        public static Thread T2;
        //This AutoResetEvent starts out non-signalled
        public static AutoResetEvent ar1 = new AutoResetEvent(false);
        //This AutoResetEvent starts out signalled
        public static AutoResetEvent ar2 = new AutoResetEvent(true);

        static void Main(string[] args)
        {

            T1 = new Thread((ThreadStart)delegate
                {
                    Console.WriteLine(
                        "T1 is simulating some work by sleeping for 5 secs");
                    //calling sleep to simulate some work
                    Thread.Sleep(5000);
                    Console.WriteLine(
                        "T1 is just about to set AutoResetEvent ar1");
                    //alert waiting thread(s)
                    ar1.Set();
                });

            T2 = new Thread((ThreadStart)delegate
            {
                //wait for AutoResetEvent ar1, this will wait for ar1 to be signalled
                //from some other thread
                Console.WriteLine(
                    "T2 starting to wait for AutoResetEvent ar1, at time {0}", 
                    DateTime.Now.ToLongTimeString());
                ar1.WaitOne();
                Console.WriteLine(
                    "T2 finished waiting for AutoResetEvent ar1, at time {0}", 
                    DateTime.Now.ToLongTimeString());

                //wait for AutoResetEvent ar2, this will skip straight through
                //as AutoResetEvent ar2 started out in the signalled state
                Console.WriteLine(
                    "T2 starting to wait for AutoResetEvent ar2, at time {0}",
                    DateTime.Now.ToLongTimeString());
                ar2.WaitOne();
                Console.WriteLine(
                    "T2 finished waiting for AutoResetEvent ar2, at time {0}",
                    DateTime.Now.ToLongTimeString());
            });
            
            T1.Name = "T1";
            T2.Name = "T2";
            T1.Start();
            T2.Start();
            Console.ReadLine();
        }
    }
}

This results in the following output, where it can be seen that T1 waits for 5 secs (simulated work) and T2 waits for the AutoResetEvent "ar1" to be put into signaled state, but doesn't have to wait for AutoResetEvent "ar2" as it's already in the signaled state when it is constructed.

 

 

 

ManualResetEvent

From MSDN:

"When a thread begins an activity that must complete before other threads proceed, it calls Reset to putManualResetEvent in the non-signaled state. This thread can be thought of as controlling theManualResetEvent. Threads that call WaitOne on the ManualResetEvent will block, awaiting the signal. When the controlling thread completes the activity, it calls Set to signal that the waiting threads can proceed. All waiting threads are released.

Once it has been signaled, ManualResetEvent remains signaled until it is manually reset. That is, calls to WaitOne return immediately."

 

 

using System;
using System.Threading;

namespace ManualResetEventTest
{
    /// <summary>
    /// This simple class demonstrates the usage of an ManualResetEvent
    /// in 2 different scenarios, bith in the non-signalled state and the 
    /// signalled state
    /// </summary>
    class Program
    {
        public static Thread T1;
        public static Thread T2;
        public static Thread T3;
        //This ManualResetEvent starts out non-signalled
        public static ManualResetEvent mr1 = new ManualResetEvent(false);

        static void Main(string[] args)
        {
            T1 = new Thread((ThreadStart)delegate
            {
                Console.WriteLine(
                    "T1 is simulating some work by sleeping for 5 secs");
                //calling sleep to simulate some work
                Thread.Sleep(5000);
                Console.WriteLine(
                    "T1 is just about to set ManualResetEvent ar1");
                //alert waiting thread(s)
                mr1.Set();
            });

            T2 = new Thread((ThreadStart)delegate
            {
                //wait for ManualResetEvent mr1, this will wait for ar1
                //to be signalled from some other thread
                Console.WriteLine(
                    "T2 starting to wait for ManualResetEvent mr1, at time {0}",
                    DateTime.Now.ToLongTimeString());
                mr1.WaitOne();
                Console.WriteLine(
                    "T2 finished waiting for ManualResetEvent mr1, at time {0}",
                    DateTime.Now.ToLongTimeString());
            });

            T3 = new Thread((ThreadStart)delegate
            {
                //wait for ManualResetEvent mr1, this will wait for ar1
                //to be signalled from some other thread
                Console.WriteLine(
                    "T3 starting to wait for ManualResetEvent mr1, at time {0}",
                    DateTime.Now.ToLongTimeString());
                mr1.WaitOne();
                Console.WriteLine(
                    "T3 finished waiting for ManualResetEvent mr1, at time {0}",
                    DateTime.Now.ToLongTimeString());
            });

            T1.Name = "T1";
            T2.Name = "T2";
            T3.Name = "T3";
            T1.Start();
            T2.Start();
            T3.Start();
            Console.ReadLine();

        }
    }
}

Which results in the following screenshot:

It can be seen that three threads (T1-T3) are started, T2 and T3 are both waiting on the ManualResetEvent "mr1", which is only put into the signaled state within thread T1's code block. When T1 puts the ManualResetEvent"mr1" into the signaled state (by calling the Set() method), this allows waiting threads to proceed. As T2 and T3 are both waiting on the ManualResetEvent "mr1", and it is in the signaled state, both T2 and T3 proceed. TheManualResetEvent "mr1" is never reset, so both threads T2 and T3 are free to proceed to run their respective code blocks.

 

 

Mutex

A Mutex works in much the same way as the lock statement (that we will look at in the Critical sections section below), so I won't harp on about it too much. But the main advantage the Mutex has over lock statements and theMonitor object is that it can work across multiple processes, which provides a computer-wide lock rather than application wide.

 

 

 

 

 

 

转载于:https://www.cnblogs.com/zendevelop/archive/2011/12/05/2276848.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值