4.0第二十章 线程,任务和同步

来源:互联网 发布:站内搜索数据库 编辑:程序博客网 时间:2024/06/01 10:42
.net 4.0新的名称空间system.threading.tasks
1)启动新任务的方式,
第一种是实例化的TaskFactory类,把方法传递给StartNew方法,就会立即启动线程
TaskFactory tf=new TaskFactory();
Task t1=tf.StartNew(TaskMethod);
Task t1=Task.Factory.StartNew(TaskMethod);
第二种是使用Task的构造函数,再调用Start()方法。
Task t2=new Task(TaskMethod);
t2.Start();
2)连续的任务
通过Task可以指定在完成任务后,应开始运行另一个特定任务。
连续任务通过在任务上调用ContinuteWith来定义。
在continuewith的子任务必须要带一个Task类型的参数
 static void Main(string[] args)
        {
            Task t1 = new Task(FirstJob);
            Task t2 = t1.ContinueWith(SecondJob);
            Task t3 = t2.ContinueWith(SecondJob);


            t1.Start();
            Console.ReadKey();
        }
        static void FirstJob()
        {
            Console.WriteLine("the first");
        }


        static void SecondJob(Task t)
        {
            Console.WriteLine(t.Id);
            Console.WriteLine("the 2nd");
        }
输出结果:
 


Parallel类
Paralle1类使用多个任务,会自动用多个线程来完成这个作业。


3)用Parallel.For()方法循环
Parallel.For类似于for循环。迭代的顺序是不能保证的
  //在ForO方法中,前两个参数定义了循环的开头和结束。示例从0迭代到9。第3个参数是一个
            //Action<int>委托。整数参数是循环的迭代次数,该参数被传递给Action<int>委托引用的方法。
            ParallelLoopResult result = Parallel.For(0, 10, i => {
                Console.WriteLine("{0}",i);
            });
            Console.WriteLine(result.IsCompleted);


            //也可以提前中断Pamlle1.ForO方法。ForO方法的一个重载版本接受第3个Action<int>
//ParalleLoopState类型的参数。使用这些参数定义一个方法,就可以调用ParalleLoopstate的Break
//或stop0方法,以影响循环的结果。
            ParallelLoopResult result2 = Parallel.For(0, 10, (int i, ParallelLoopState pls) => {
                Console.WriteLine("{0}", i);
                if (i > 15)
                {
                    pls.Break();
                }
            });
在调用 Stop 或 Break 后,循环中的其他线程可能会继续运行一段时间(这不受应用程序开发人员的控制)


4)用Parallel.For(TLocal)方法循环
分为三个部分,第一部分(Init)参数类型是func<TLocal>,这个例子中是Func<String>,即返回String类型的方法。这个方法用于执行迭代的每个线程调用一次
第二部分(body)例子中参数类型是Func<int,ParallelLoopState,String>第一个参数是循环迭代,第二个参数允许停止循环,第三个参数,接受从Init部分返回的值,该循环体还需要一个返回值。
第三部分(finally)本例中接受一个字符串。该方法仅对于每个线程调用一次,这是一个线程推出方法。
  Parallel.For<string>(0, 20, () =>
            {
                Console.WriteLine("Init thread {0},task {1}", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);
                return "aaa";//这个值会传递给第二部分的str1
            },
           (i, pls, str1) =>
           {
               Console.WriteLine("body i {0} str1 {1} thread {2} task {3} loopState {4}", i, str1, Thread.CurrentThread.ManagedThreadId, Task.CurrentId, pls.IsStopped);
               return string.Format("i {0}", i);
           },
           (str) =>//接受第二部分穿过来的值
           {
               Console.WriteLine("finally {0}", str);
           }
            );


Parallel类
Paralle会自动决定启用多少线程来完成指定作业。
example 1
 //在Parallel.For方法中,前两个参数定义了循环的开头和结束。示例从0迭代到9。第3个参数是一个Action<int>委托。
 Parallel.For(0,10,i=>{
                Console.WriteLine("{0}",i);
            });
 Console.WriteLine("Done");


 例子 1.4 Semaphore ,用parallel.For方式改写
 Parallel.For(0, tckList.Count, i => {
                Console.WriteLine("Calculating {0}'s VolSpot and VolValue;Thread {1}...", tckList[i].ToString(), Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(1000);
            });
            Console.WriteLine("Done");


CountDownEvent

System.Threading.CountdownEvent 是一个同步基元,它在收到一定次数的信号之后,将会解除对其等待线程的锁定。 

使用singal减少一个信号

class Program
    {
        static void Main(string[] args)
        {
            CountdownEvent cd = new CountdownEvent(3);
            for (int i = 0; i < 3; i++)
            {
                DoJob job=new DoJob(cd);
                var TaskFactory = new TaskFactory();
                TaskFactory.StartNew(job.DomyJob);
            }
            cd.Wait();
            Console.WriteLine("Done");          
            Console.ReadLine();
        }       
       
    }


     class DoJob
    {
        private CountdownEvent cde;
        public DoJob(CountdownEvent ev)
        {
            this.cde = ev;
        }


        public  void DomyJob()
        {


            Thread.Sleep(900);
            Console.WriteLine("New Task Start");
            cde.Signal();
        }
    }

0 0