随笔分类 - 多线程、异步、IO
摘要:本节中主要介绍了两个方法的使用,一个是等待组中全部任务都执行结束的Task.WhenAll()方法,另一个是只要组中一个方法执行结束都执行的Task.WhenAny()方法。 具体使用,如下演示代码所示。 static void Main(string[] args) { // 第一种方式 通过Ta
阅读全文
摘要:注意:返回void的异常方法不会等待。这是因为从async void方法抛出的异常无法捕获,因此,异步方法最好返回一个Task类型。处理程序方法或者重写基类方法不受此规则限制。 异步方法的异常较好的一个处理方式,就是使用await关键字,将其放在try/catch语句中。如下: public sta
阅读全文
摘要:在TAP模式中,实现取消选项和之前的异步模式一样,都是使用CancellationToken来实现,但是不同的是Task构造函数允许传入一个CancellationToken,从而在任务实际启动之前取消它。 static void Main(string[] args) { var cts = ne
阅读全文
摘要:本节将展示如何设置相互依赖的任务。我们将学习如何创建一个任务,使其在父任务完成后才会被运行。另外,将探寻为非常短暂的任务节省线程开销的可能性。 class Program { static void Main(string[] args) { var firstTask = new Task<int
阅读全文
摘要:本节将描述如何从任务中获取结果值。我们将通过几个场景来了解在线程池中和主线程中运行任务的不同之处。 class Program { static void Main(string[] args) { TaskMethod("Main Thread Task");//该方法是被同步执行的。很显然它不是
阅读全文
摘要:我们在之前的章节中学习了什么是线程,如何使用线程,以及为什么需要线程池。使用线程池可以使我们在减少并行度花销时节省操作系统资源。我们可以认为线程池是一个抽象层,其向程序员隐藏了使用线程的细节,使我们专心处理程序逻辑,而不是各种线程,问题。 然而使用线程池也相当复杂。从线程池的工作线程中获取结果并不容
阅读全文
摘要:三种方式 通过使用轮循操作来检查IsCancellationRequested是否为true,是则需要取消当前操作过程(直接使用return) 通过抛出一个OperationCanceledException异常来终止操作(操作之外的代码控制取消过程) 注册一个回调函数(操作取消时,线程池将调用该函
阅读全文
摘要:展示线程池如何工作于大量的异步操作,以及它与创建大量单独的线程的方式有什么不同。 大量创建线程(消耗内存、CPU系统资源,请观察) 使用线程池:执行的时间更长,但对系统资源消耗要小的多 using System; using System.Text; using System.Threading;
阅读全文
摘要:static void Main(string[] args) { const int x = 1; const int y = 2; const string lambdaState = "lambda state 2"; //将AsyncOperation方法放入线程池执行 ThreadPool
阅读全文
摘要:APM(Asynchronous Programming Model)是.Net 旧版本中广泛使用的异步编程模型,但在现代编程中,更推荐使用TPL(Task Parallel Library),他是.Net 4.0 之后带来的新特性 TaskAsync。 static void Main(strin
阅读全文
摘要:volatile :适用于多线程的情况,因为单线程的代码如果被编译器优化了,是不会出现问题的。 单线程是串行的,在线程方法外修改字段的值是不会有影响的。 如果是多线程在线程方法外修改了这个线程内的某个值,是会影响到这个方法的执行的(但此时如果代码被编译器优化了,那代码执行时) 使用Volatile对
阅读全文
摘要:同时多个线程来(如从字典中)读取数据,还有另外几个线程(如向该字典中)写入数据 比如:WEB中对缓存的读写操作(一般是一边是大量用户读取【如果读取不到,就加写锁,然后写数据到缓存】) 由于锁 ( lock 和 Monitor ) 是线程独占式访问的,所以其对性能的影响还是蛮大的,那有没有一种方式可是
阅读全文
摘要:网站被用户加载后,可能你会打开/product/index这种页面,它将会在服务器端产生一个线程,这个线程我们称为主线程,当然你的程序中也可以通过Thread类建立其它线程,但只要你加开页面,就会有一个主线程被加载,这是一定的,我们可以通过Thread.CurrentThread静态属性来获得当前运
阅读全文
摘要:Barrier(屏障)是一种自定义的同步原语(synchronization primitive),它解决了多个线程(参与者)在多个阶段之间的并发和协调问题。 1)多个参与者执行相同的几个阶段的操作 2)在每一个阶段内,多个参与者并发执行 3)一个屏障点代表一个阶段的结束 4)一个参与者运行至屏障点
阅读全文
摘要:火箭【主线程】起飞前会等待一个倒计时数【定量的子线程不断完成任务,并减少计数】) 当主程序启动时,创建了一个CountdownEvent实例,在其构造函数中指定了当两个操作完成时会发生信号。然后我们启动了两个线程,当他们执行完成后会发出信号。一旦第二个线程完成,主线程会从等待CountdownEve
阅读全文
摘要:ManualResetEventSlim的整个工作方法有点像人群通过大门,AutoResetEvent事件像一个旋转门,一次只允许一人通过。ManualResetEventSlim是ManualResetEvent的混合版本,一直保持大门敞开直到手动调用Reset方法。当调用_mainEvent.S
阅读全文
摘要:主要作用:从一个线程向另一个线程发送通知,进行线程同步。 有点像旋转门,一次只允许一个人通过(一边等待,一边通过,如此循环) AutoResetEvent 常常被用来在两个线程之间进行信号发送,两个线程共享相同的AutoResetEvent对象,线程可以通过调用AutoResetEvent对象的Wa
阅读全文
摘要:Semaphore:信号量。 相当于一个计数器,记录一个共享资源被访问线程的个数;好比有两个或者更多个办事窗口,他们都做同一件事;假设有4个窗口,五个窗口都没人访问的时候计数器为4;有一个窗口被占用计数器减1,为3;全部被占用则计数器为0;这时候其他人想要访问就必须等待占用结束后计数器加1; Sem
阅读全文
摘要:同一时刻,只能有一个线程持有该锁! 使用Mutex互斥锁来同步两个单独的程序(可以两次运行该程序,查看运行结果) static void Main(string[] args) { const string MutexName = "CSharpThreadingCookbook"; using (
阅读全文
摘要:原则: 线程都不应该抛出未捕获的exception(有矛盾在自己家解决,别人哪有时间管你家吵架!) 也就是说各个线程需要自己把自己的exception处理掉。 话不多说,直接看代码 static void Main(string[] args) { //第一个会抛出异常的线程(但这个线程方法内部作了
阅读全文