基元用户模式构造--互锁构造 Interlocked 实现的异步web请求实例

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Net.Http;
  5 using System.Text;
  6 using System.Threading;
  7 using System.Threading.Tasks;
  8
  9 namespace Test
 10 {
 11     enum CoordinationStatus
 12     {
 13         AllDone,
 14         Cancel,
 15         Timeout
 16     }
 17     class AsyncCoordinator
 18     {
 19         private int statusReported = 0;
 20         private int op_count = 1;
 21
 22         private Action<CoordinationStatus> callback;
 23         private Timer timer;
 24
 25         public void AboutToBegin(int num = 1)
 26         {
 27             Interlocked.Add(ref op_count, num);
 28         }
 29
 30         public void JustToEnd()
 31         {
 32             if (Interlocked.Decrement(ref op_count) == 0)
 33             {
 34                 ReportStatus(CoordinationStatus.AllDone);
 35             }
 36         }
 37
 38         public void AllBegun(Action<CoordinationStatus> callback, int timeout = Timeout.Infinite)
 39         {
 40             this.callback = callback;
 41             if (timeout != Timeout.Infinite)
 42             {
 43                 timer = new Timer(Expired, null, timeout, Timeout.Infinite);
 44             }
 45             JustToEnd();
 46         }
 47
 48         private void Expired(object obj)
 49         {
 50             ReportStatus(CoordinationStatus.Cancel);
 51         }
 52         public void Cancel()
 53         {
 54             ReportStatus(CoordinationStatus.Cancel);
 55         }
 56         private void ReportStatus(CoordinationStatus status)
 57         {
 58             if (Interlocked.Exchange(ref statusReported, 1) == 0)
 59             {
 60                 callback(status);
 61             }
 62         }
 63
 64
 65
 66     }
 67
 68     class MultiWebRequests
 69     {
 70         private AsyncCoordinator coordinator = new AsyncCoordinator();
 71
 72         private Dictionary<string, object> servers = new Dictionary<string, object>(){
 73             {"http://www.baidu.com",null},
 74             {"http://www.sina.com",null},
 75             {"http://www.qq.com",null},
 76         };
 77
 78         public MultiWebRequests()
 79         {
 80
 81             var http = new HttpClient();
 82             foreach (var url in servers.Keys)
 83             {
 84                 //发送了一个请求
 85                 coordinator.AboutToBegin(1);
 86                 http.GetByteArrayAsync(url).ContinueWith(task => GetResult(url, task));
 87             }
 88             //所有请求发送完毕
 89             coordinator.AllBegun(AllDone, Timeout.Infinite);
 90         }
 91
 92         private void GetResult(string server, Task<byte[]> task)
 93         {
 94             object res;
 95             if (task.Exception != null)
 96             {
 97                 res = task.Exception.InnerExceptions;
 98             }
 99             else
100             {
101                 res = task.Result.Length;
102             }
103             servers[server] = res;
104             //完成了一个请求
105             coordinator.JustToEnd();
106         }
107
108         public void Cancel()
109         {
110             coordinator.Cancel();
111         }
112
113         private void AllDone(CoordinationStatus status)
114         {
115             switch (status)
116             {
117                 case CoordinationStatus.AllDone:
118                     Console.WriteLine("allDone: ");
119
120                     foreach (var item in servers)
121                     {
122                         Console.Write(item.Key);
123                         object val = item.Value;
124                         if (val is Exception)
125                         {
126                             Console.WriteLine("Exception: {0}",val.GetType().Name);
127                         }
128                         else
129                         {
130                             Console.WriteLine("returned  {0:N0} bytes",val);
131                         }
132                     }
133                     break;
134                 case CoordinationStatus.Cancel:
135                     break;
136                 case CoordinationStatus.Timeout:
137                     break;
138                 default:
139                     break;
140             }
141         }
142     }
143 }
时间: 2024-10-10 06:55:55

基元用户模式构造--互锁构造 Interlocked 实现的异步web请求实例的相关文章

[叩响C#之门]写给初学者:多线程系列(七)——互锁(Interlocked类)

前言:我第一次接触“线程”的概念时,觉得它深奥难懂,看了好多本书,花了很长时间才领悟到它的真谛.现在我就以一个初学者的心态,把我所理解的“多线程”描述给大家.这一次是系列文章,比较完整的展示与线程相关的基本概念.希望对初学者有所帮助.语言比较精炼,有些地方需要反复阅读. 目录(欲看前面的章节,请点击下面的链接 ) 第21章 多 线 程 21.1 线程的概念 21.2 Thread类 21.3 线程的优先级 21.4 线程的插入 21.5 线程的状态 21.6 线程的同步 21.6.1 线程同步的

【C#进阶系列】28 基元线程同步构造

多个线程同时访问共享数据时,线程同步能防止数据损坏.之所以要强调同时,是因为线程同步问题实际上就是计时问题. 不需要线程同步是最理想的情况,因为线程同步一般很繁琐,涉及到线程同步锁的获取和释放,容易遗漏,而且锁会损耗性能,获取和释放锁都需要时间,最后锁的玩法就在于一次只能让一个线程访问数据,那么就会阻塞线程,阻塞线程就会让额外的线程产生,阻塞越多,线程越多,线程过多的坏处就不谈了. 所以可以避免线程同步的话就应该去避免,尽量不要去使用静态字段这样的共享数据. 类库和线程安全 .net类库保证了所

Clr Via C#读书笔记----基元线程同步构造

重点在于多个线程同时访问,保持线程的同步. 线程同步的问题: 1,线程同步比较繁琐,而且容易写错. 2,线程同步会损害性能,获取和释放一个锁是需要时间. 3,线程同步一次只允许一个线程访问资源. 类库和线程安全, 一个线程安全的发那个发意味着两个线程试图同时访问数据时,数据不会被破坏. 基元用户模式和内核模式构造 基元:指代码中最简单的构造,有两种基元构造:用户模式和内核模式. 1,基元用户模式比基元内核模式速度要快,因为直接使用特殊的cpu指令来协调线程,在硬件中发生的. 2,基元用户模式构造

异步编程(二)用户模式线程同步

基元线程同步构造 多个线程同时访问共享数据时,线程同步能防止数据损坏.不需要线程同步是最理想的情况,因为线程同步存在许多问题. 第一个问题就是它比较繁琐,而且很容易写错. 第二个问题是,他们会损害性能.获取和释放锁是需要时间的. 第三个问题是,他们一次只允许一个线程访问资源,就可能导致其他线程被阻塞,使用多线程是为了提高效率,而阻塞无疑降低了你的效率. 综上所述,线程同步是一件不好的事情,所以在设计自己的应用程序时,应尽可能避免进行线程同步.具体就是避免使用像静态字段这样的共享数据.线程用new

[.net]基元线程同步构造

1 /* 基元线程同步构造 2 用户模式构造: 3 易变构造(Volatile Construct) 4 互锁构造(Interlocked Construct):自旋锁(Spinlock) 乐观锁(Optimistic Concurrency Control,乐观并发控制) 5 内核模式构造: 6 事件构造(Event) 7 信号量构造(Semaphore) 8 互斥体构造(Mutex) 9 */ 10 11 //易变构造,Volatile.Write()之前的所有字段写入操作,必须再该方法调用

[并发并行]_[线程同步]_[Windows用户态下的原子访问的互锁函数]

场景: 1. 多线程编程时,有时候需要统计某个变量或对象的创建个数或者是根据某个变量值来判断是否需要继续执行下去,这时候互锁函数是比较高效的方案之一了. 说明: 1.原子访问:(互锁函数族) -- 原子访问,指线程在访问资源时能够确保所有其他线程都不在同一时间内访问相同的资源. -- 调用一个互锁函数通常只需要执行几个CPU周期(通常小于50),并且不需要从用户模式转换为内核模式(通常这需要1000个CPU周期). -- 互锁函数是CPU硬件支持的,如果是x86处理器,互锁函数会向总线发出一个硬

CLR via C#深解笔记三 - 基元类型、引用类型和值类型 | 类型和成员基础 | 常量和字段

编程语言的基元类型 某些数据类型如此常用,以至于许多编译器允许代码以简化的语法来操纵它们. System.Int32 a = new System.Int32();  // a = 0 a = 1; 等价于: int a = 1; 这种语法不仅增强了代码的可读性,其生成的IL代码与使用System.Int32时生成的IL代码是完全一致的. 编译器直接支持的数据类型称为基元类型(primitive type).基元类型直接映射到Framework类库(FCL)中存在的类型.如C#中,int直接映射

深入理解.NET Core的基元(二) - 共享框架

原文:Deep-dive into .NET Core primitives, part 2: the shared framework 作者:Nate McMaster 译文:深入理解.NET Core的基元(二) - 共享框架 作者: Lamond Lu 本篇是之前翻译过的<深入理解.NET Core的基元: deps.json, runtimeconfig.json, dll文件>的后续,这个系列作者暂时只写了3篇,虽然有一些内容和.NET Core 3.0已经不兼容了,但是大部分的原理

第8章 用户模式下的线程同步

8.1 原子访问:Interlocked系列函数(Interlock英文为互锁的意思) (1)原子访问的原理 ①原子访问:指的是一线程在访问某个资源的同时能够保证没有其他线程会在同一时刻访问该资源. ②从汇编的角度看,哪怕很简单的一条高级语言都可以被编译成多条的机器指令.在多线程环境下,这条语句的执行就可能被打断.而在打断期间,其中间结果可能己经被其他线程更改过,从而导致错误的结果. ③在Intelx86指令体系中,有些运算指令加上lock前缀就可以保证该指令操作的原子性.其原理是CPU执行该指