前言

学习C#两个多月了,像当初实习做PHP开发一样,也是由着一个个Feature需求,慢慢掌握了很多相关的编程技巧。本次主要记录下学习C# 多线程的相关知识。

参考书籍:《Csharp高级编程(第7版)》

1.使用线程的原因

不过运行多个线程也要注意一些问题:他们可以同时运行,但是如果线程访问相同的数据,就很容易出问题,必须实现同步机制

 2.理解线程

线程是程序中独立的指令流。C#编写的程序都有一个入口点(即Main()方法),程序从该方法的第一条开始执行,直到方法返回为止。这种程序结构非常适合用于一个有任务序列的程序,但是程序常常需要同时完成多个任务。

这就要用到多个线程,比如Word的拼写检查器的工作原理是这样的:一个线程等待用户输入,另一个线程进行后台搜索,第3个线程将写入的数据保存在临时文件中,第4个线程从Internet上下载其他数据。

理解线程很重要的一点其实是理解线程和进程的关系:

3.创建线程的方式

  • 异步委托

创建线程的一种简单地方式是定义委托,并异步调用它。委托是方法的类型安全的引用,它使用线程池来完成异步任务。

代码实例:

使用投票的例子,并检查委托是否完成了它的任务。等待异步委托结果的四种方式:

(1)轮询

Delegate类提供了BeginInvoke()方法,通过其返回类型IAsyncResult ,可以获取委托的相关信息,并检验它是否完成了任务。只要委托没有完成其任务,程序的主线程就继续执行while循环。

(2)等待句柄

使用与IAsyncResult 相关联的等待句柄。使用AsyncWaitHandle属性可以访问等待句柄,该属性可以返回一个WaitHandle类型的对象,它可以等待委托线程完成其任务。

(3)异步回调

(4)Lambda表达式 

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics;namespace Wrox.ProCSharp.Threading
{class Program{static int TakesAWhile(int data, int ms){Console.WriteLine("TakesAWhile started");Thread.Sleep(ms);Console.WriteLine("TakesAWhile completed");return ++data;}
     //要从委托中调用这个方法,必须定义一个有相同参数和返回类型的的委托public delegate int TakesAWhileDelegate(int data, int ms);static void Main(){// synchronous// TakesAWhile(1, 3000);TakesAWhileDelegate d1 = TakesAWhile;// (1)polling轮询//IAsyncResult ar = d1.BeginInvoke(1, 3000, null, null);//while (!ar.IsCompleted)//{ //   // doing something else//   Console.Write("."); //   Thread.Sleep(50);//}//int result = d1.EndInvoke(ar);//Console.WriteLine("result: {0}", result);// (2)wait handle//IAsyncResult ar = d1.BeginInvoke(1, 3000, null, null);//while (true)//{//   Console.Write(".");//   if (ar.AsyncWaitHandle.WaitOne(50, false))//   {//      Console.WriteLine("Can get the result now");//      break;//   }//}//int result = d1.EndInvoke(ar);//Console.WriteLine("result: {0}", result);// (3)async callback//d1.BeginInvoke(1, 3000, TakesAWhileCompleted, d1);//for (int i = 0; i < 100; i++)//{//   Console.Write(".");//   Thread.Sleep(50);//}//(4)Lambda expression:可以直接访问作用域外的变量d1,所以不需要把一个值赋予BeginInvoke()方法的最后一个参数d1.BeginInvoke(1, 3000,ar =>{int result = d1.EndInvoke(ar);Console.WriteLine("result: {0}", result);},null);for (int i = 0; i < 100; i++){Console.Write(".");Thread.Sleep(50);}}static void TakesAWhileCompleted(IAsyncResult ar){if (ar == null) throw new ArgumentNullException("ar");TakesAWhileDelegate d1 = ar.AsyncState as TakesAWhileDelegate;Trace.Assert(d1 != null, "Invalid object type");int result = d1.EndInvoke(ar);Console.WriteLine("result: {0}", result);}}
}

运行结果:

代码实例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;namespace Wrox.ProCSharp.Threading
{public class MyThread{private string data;public MyThread(string data){this.data = data;}public void ThreadMain(){Console.WriteLine("Running in a thread, data: {0}", data);}}public struct Data{public string Message;}class Program{static void Main(){FirstThread();//var t1 = new Thread(Prio);//t1.Name = "First";//var t2 = new Thread(Prio);//t2.Name = "Second";//t1.Priority = ThreadPriority.Highest;//t2.Priority = ThreadPriority.Lowest;//t1.Start();//t2.Start();//var t1 = new Thread(ThreadMain);//t1.Name = "MyNewThread1";//t1.IsBackground = true;//t1.Start();//Console.WriteLine("Main thread ending now...");//var d = new Data { Message = "Info" };//var t2 = new Thread(ThreadMainWithParameters);//t2.Start(d);//var obj = new MyThread("info");//var t3 = new Thread(obj.ThreadMain);//t3.Start();}static void Prio(){for (int i = 0; i < 10000; i++){Console.WriteLine("{0}, {1}", Thread.CurrentThread.Name, i);}}static void ThreadMain(){Console.WriteLine("Thread {0} started", Thread.CurrentThread.Name);Thread.Sleep(3000);// Console.WriteLine("Running in the thread {0}, id: {1}.", Thread.CurrentThread.Name, Thread.CurrentThread.ManagedThreadId);Console.WriteLine("Thread {0} completed", Thread.CurrentThread.Name);}static void ThreadMainWithParameters(object o){Data d = (Data)o;Console.WriteLine("Running in a thread, received {0}", d.Message);}static void FirstThread(){new Thread(() => Console.WriteLine("Running in a thread, id: {0}", Thread.CurrentThread.ManagedThreadId)).Start();Console.WriteLine("This is the main thread, id: {0}", Thread.CurrentThread.ManagedThreadId);}}
}

运行结果:

代码实例:

using System;
using System.Threading;namespace Wrox.ProCSharp.Threading
{class Program{static void Main(){int nWorkerThreads;int nCompletionPortThreads;ThreadPool.GetMaxThreads(out nWorkerThreads, out nCompletionPortThreads);Console.WriteLine("Max worker threads: {0}, I/O completion threads: {1}", nWorkerThreads, nCompletionPortThreads);for (int i = 0; i < 5; i++){ThreadPool.QueueUserWorkItem(JobForAThread);}Thread.Sleep(3000);}static void JobForAThread(object state){for (int i = 0; i < 3; i++){Console.WriteLine("loop {0}, running inside pooled thread {1}", i,Thread.CurrentThread.ManagedThreadId);Thread.Sleep(50);}}}
}

运行结果:

代码实例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.IO;namespace TaskSamples
{class Program{static void Main(){// ParallelDemo();SimpleTask();// ContinuationTask();// ParentAndChild();// ResultsFromTasks();Thread.Sleep(5000);//ParentAndChild();// HierarchyTasks("c:\\");//Parallel.f//Task t1 = new Task(() => Console.WriteLine("running in a task"));//Task t2 = new Task(() => Console.WriteLine("running in a task"));//for (int i = 0; i < 10; i++)//{//    Task t1 = new Task(o =>//    {//        Console.WriteLine("running in a task {0}", Thread.CurrentThread.ManagedThreadId);//        Thread.Sleep(500);//        Console.WriteLine("still running {0}", Thread.CurrentThread.ManagedThreadId);//    }, "data", TaskCreationOptions.None);//    // t1.RunSynchronously();//    t1.Start();//}//Console.WriteLine("start sleep main");//Thread.Sleep(3000);//Console.WriteLine("main thread");}static void ResultsFromTasks(){var t1 = new Task<Tuple<int,int>>(TaskWithResult, Tuple.Create<int, int>(8, 3));t1.Start();Console.WriteLine(t1.Result);t1.Wait();Console.WriteLine("result from task: {0} {1}", t1.Result.Item1, t1.Result.Item2);}static Tuple<int, int> TaskWithResult(object division){Tuple<int, int> div = (Tuple<int, int>)division;int result = div.Item1 / div.Item2;int reminder = div.Item1 % div.Item2;Console.WriteLine("task creates a result...");return Tuple.Create<int, int>(result, reminder);}static void SimpleTask(){// using task factoryTaskFactory tf = new TaskFactory();Task t1 = tf.StartNew(TaskMethod);// using the task factory via a taskTask t2 = Task.Factory.StartNew(TaskMethod);Console.WriteLine(Thread.CurrentThread.ManagedThreadId);// using Task constructorTask t3 = new Task(TaskMethod);// t3.Start();t3.RunSynchronously();Task t4 = new Task(TaskMethod, TaskCreationOptions.PreferFairness);t4.Start();}static void ContinuationTask(){Task t1 = new Task(DoOnFirst);Task t2 = t1.ContinueWith(DoOnSecond);Task t3 = t1.ContinueWith(DoOnSecond);Task t4 = t2.ContinueWith(DoOnSecond);          Task t5 = t1.ContinueWith(DoOnError, TaskContinuationOptions.OnlyOnFaulted);t1.Start();Thread.Sleep(5000);}static void DoOnFirst(){Console.WriteLine("doing some task {0}", Task.CurrentId);Thread.Sleep(3000);}static void DoOnSecond(Task t){Console.WriteLine("task {0} finished", t.Id);Console.WriteLine("this task id {0}", Task.CurrentId);Console.WriteLine("do some cleanup");Thread.Sleep(3000);}static void DoOnError(Task t){Console.WriteLine("task {0} had an error!", t.Id);Console.WriteLine("my id {0}", Task.CurrentId);Console.WriteLine("do some cleanup");}static void ParentAndChild(){Task parent = new Task(ParentTask);parent.Start();Thread.Sleep(2000);Console.WriteLine(parent.Status);Thread.Sleep(4000);Console.WriteLine(parent.Status);}static void ParentTask(){Console.WriteLine("task id {0}", Task.CurrentId);Task child = new Task(ChildTask); // , TaskCreationOptions.DetachedFromParent);child.Start();Thread.Sleep(1000);Console.WriteLine("parent started child");// Thread.Sleep(3000);}static void ChildTask(){// Console.WriteLine("task id {0}, parent: {1}", Task.Current.Id, Task.Current.Parent.Id);Console.WriteLine("child");Thread.Sleep(5000);Console.WriteLine("child finished");}static void TaskMethod(){Console.WriteLine("running in a task");Console.WriteLine("Task id: {0} {1}", Task.CurrentId, Thread.CurrentThread.ManagedThreadId);}static void ParallelDemo(){// Parallel.For(0, 5, i => Console.WriteLine(i));Parallel.For<string>(0, 20, () => "abcd",(x, ls, str) =>{Console.WriteLine(x);return "defg";},(str) =>{Console.WriteLine("action {0}", str);});ParallelOptions po = new ParallelOptions();}//static void ParentAndChild()//{//    TaskFactory factory = new TaskFactory();//    var t1 = factory.StartNew(() =>//        {//            Console.WriteLine("parent task {0}", Task.CurrentId);//            factory.StartNew(() =>//                {//                    Console.WriteLine("child task {0}", Task.CurrentId);//                    Thread.Sleep(2000);//                    Console.WriteLine("finished child");//                }, TaskCreationOptions.AttachedToParent);//            Console.WriteLine("finished parent");//        });//    t1.Wait();//}}
}

运行结果:

代码实例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;namespace Wrox.ProCSharp.Threading
{class Program{static void Main(){//ParallelFor();//ParallelForeach();ParallelInvoke();}static void ParallelInvoke(){//并行运行多个任务:Parallel.Invoke()方法允许传递一个Action委托数组,其中指定应运行的方法Parallel.Invoke(Foo, Bar);}static void Foo(){Console.WriteLine("foo");}static void Bar(){Console.WriteLine("bar");}static void ParallelForeach(){string[] data = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve"};//异步方式遍历ParallelLoopResult result =Parallel.ForEach<string>(data, s =>{Console.WriteLine(s);});Parallel.ForEach<string>(data,(s, pls, l) =>{Console.WriteLine("{0} {1}", s, l);});}static void ParallelFor(){//ParallelLoopResult result =//    Parallel.For(0, 10, i =>//        {//            Console.WriteLine("{0}, task: {1}, thread: {2}", i,//               Task.CurrentId, Thread.CurrentThread.ManagedThreadId);//            Thread.Sleep(10);//        });//Console.WriteLine(result.IsCompleted);//ParallelLoopResult result =//    Parallel.For(10, 40, (int i, ParallelLoopState pls) =>//        {//            Console.WriteLine("i: {0} task {1}", i, Task.CurrentId);//            Thread.Sleep(10);//            if (i > 15)//                pls.Break();//        });//Console.WriteLine(result.IsCompleted);//Console.WriteLine("lowest break iteration: {0}", result.LowestBreakIteration);Parallel.For<string>(0, 20,() =>{// invoked once for each threadConsole.WriteLine("init thread {0}, task {1}", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);return String.Format("t{0}", Thread.CurrentThread.ManagedThreadId);},(i, pls, str1) =>{// invoked for each memberConsole.WriteLine("body i {0} str1 {1} thread {2} task {3}", i, str1,Thread.CurrentThread.ManagedThreadId,Task.CurrentId);Thread.Sleep(10);return String.Format("i {0}", i);},(str1) =>{// final action on each threadConsole.WriteLine("finally {0}", str1);});}}
}

运行结果:

代码实例:

  

  

  

ps:在运行书中附带的sample时,报错:

经查证,发现这是由于StartupUri中的内容与窗口名称不一致所导致。

这部分的知识可以参考一篇译文:WPF教程(十)使用App.xaml

转载于:https://www.cnblogs.com/carsonzhu/p/7207556.html

C#读书笔记:线程,任务和同步相关推荐

  1. OCA读书笔记(9) - 管理数据同步

    9.Managing Data Concurrency 描述锁机制以及oracle如何管理数据一致性 监控和解决锁冲突 管理数据的并发--管理锁 数据的不一致: 脏读 更改丢失 幻影读 脏读: 数据是 ...

  2. 神经科学:探索脑(第四版)英文 读书笔记

    预计每周更新一章的读书笔记,加油!同步更新在知乎,微信上.欢迎关注我的微信号! 第一章--神经科学,过去,现在,未来 第二章--神经元与神经胶质细胞 第三章--静息状态的神经元外膜 第四章--动作电位

  3. 大数据之路读书笔记-03数据同步

    大数据之路读书笔记-03数据同步 如第一章所述,我们将数据采集分为日志采集和数据库数据同步两部分.数据同步技术更通用的含义是不同系统间的数据流转,有多种不同的应用场景.主数据库与备份数据库之间的数据备 ...

  4. 关于java线程同步的笔记_线程同步(JAVA笔记-线程基础篇)

    在多线程应用程序中经常会遇到线程同步的问题.比如:两个线程A.线程B可能会 "同时" 执行同一段代码,或修改同一个变量.而很多时候我们是不希望这样的. 这时候,就需要用到线程同步. ...

  5. 《深入浅出DPDK》读书笔记(五):同步互斥机制

    本文内容为读书笔记,摘自<深入浅出DPDK> 56.原子操作 原子(atom)本意是"不能被进一步分割的最小粒子",而原子操作(atomic operation)意为& ...

  6. 【板栗糖GIS】——如何使用插件将微信读书笔记同步到notion

    [板栗糖GIS]--如何使用插件将微信读书笔记同步到notion 注:本文创意以及插件开发皆是B站的[三此君] 视频链接如下: 全网唯一支持图文导出的微信读书插件,升级啦!主打一个惊艳._哔哩哔哩_b ...

  7. 多线程复习笔记(九)同步线程(中)

    一,内部锁:synchronized关键字 java中的每个对象都有一个与之关联的内部锁(intrinsic loock)这种锁也称为监视器(Monitor),这种内部锁是一种排他锁,可以保障原子性, ...

  8. 黑马毕向东Java课程笔记(day11):多线程(第一部分)——进程与线程+线程创建+线程安全与同步代码块+同步锁/死锁

    多线程好文:添加链接描述 锁机制:synchronized.Lock.Condition.volatile(原子性可见性)--参考添加链接描述 1.进程与线程概述   首先,对于CPU执行每一个程序, ...

  9. Java 线程安全问题及线程锁(读书笔记)

    多线程安全问题: 首先整理多线程同步的知识点,开头肯定是要先探讨探讨多线程安全的问题.那么嘛叫线程安全问题呢? 答: 我们知道Jvm虚拟机的设计中线程的执行是抢占式的,线程的执行时间是由底层系统决定的 ...

  10. 《Java: The Complete Reference》等书读书笔记

    春节期间读了下<Java: The Complete Reference>发现这本书写的深入浅出,我想一个问题,书中很多内容我们也知道,但是为什么我们就写不出这样一本书,这么全面,这么系统 ...

最新文章

  1. 织梦网站被黑客生成html,dedecms网站被挂马怎么处理
  2. Android组件的通讯-Intent
  3. 疯子的算法总结(五) 矩阵乘法 (矩阵快速幂)
  4. matlab标准化出现负值,为什么我求出来的约束条件是负值
  5. ejb 2.0 3.0_EJB 3.0注入和查找简介
  6. 新iPhone销量将持续走低 因为旧iPhone够用好几年
  7. 销售服务器 以次充好 判刑,销售假冒产品怎么判刑处罚,法律怎么规定的?
  8. The best GraphQL Loader for Webpack
  9. Redis设计与实现读后感
  10. php网站留言,php实现网站留言板功能
  11. 打开小米随身wifi的无线网卡功能
  12. RTL8153B ,瑞昱千兆网卡芯片 ,扩展坞HUB千兆网口芯片。
  13. win10小技巧(初)
  14. java面向对象小知识
  15. 使用MPICH构建一个四节点的集群系统
  16. java调用sap系统wsdl_Java调用Axis2用SAP WSDL生成的Stub文件
  17. 多个精美的导航样式web2.0源码
  18. Java入门篇——零基础如何学习Java
  19. 在线微量水总结与应用
  20. iview自定义表单验证

热门文章

  1. 微信小程序wx.request中post请求时data中参数不能传到后台
  2. JavaScript数据结构与算法——队列详解(上)
  3. QT: 使用qtchooser修改ubuntu默认的qmake版本
  4. 最优化:**回归/拟合方法总结
  5. ANN:ML方法与概率图模型
  6. 基于干净语言和好奇心的敏捷指导
  7. (转)用JQuery实现Fix表头表格
  8. REVIT使用中遇到的各种问题汇总
  9. oracle 11g的em界面按钮乱码的解决办法
  10. 'Request' object has no attribute 'META'报错解决