8异步和多线程

1,.NET 中实现异步的方式是使用委托的beginInvoke方法。

使用异步之后.net会创建一个线程来异步执行方法操作,主线程会继续执行程序逻辑。如果在异步执行中有回调函数,在异步方法执行完之后执行异步调用的线程回再执行回调函数中的代码。

1,首先创建一个比较耗时的私有方法用以作为异步执行的代码,后续的多线程执行代码使用的也是该代码。

 1 /// <summary>
 2         /// 一个比较耗时耗资源的私有方法
 3         /// </summary>
 4         /// <param name="name"></param>
 5         private void DoSomethingLong(string name)
 6         {
 7             Console.WriteLine($"****************DoSomethingLong Start {name} {System.Threading.Thread.CurrentThread.ManagedThreadId}***************");
 8             long lResult = 0;
 9             for (int i = 0; i < 1000000000; i++)
10             {
11                 lResult += i;
12             }
13             //Thread.Sleep(2000);
14
15             Console.WriteLine($"****************DoSomethingLong   End  {name} {System.Threading.Thread.CurrentThread.ManagedThreadId}***************");
16         }

然后声明一个委托,用私有方法实例化,调用代码如下:

 1 Action<string> act = this.DoSomethingLong;
 2
 3                 AsyncCallback callback = t =>
 4                 {
 5                     Console.WriteLine("t的值为:" + t);
 6                     Console.WriteLine($"执行callback回调函数的线程是{System.Threading.Thread.CurrentThread.ManagedThreadId}");
 7                 };
 8                 IAsyncResult asyncResult = act.BeginInvoke("btnasync_Click", callback, "标识参数");
 9
10                 Console.WriteLine("异步之外的函数执行1");
11                 Console.WriteLine("异步之外的函数执行2");
12                 Console.WriteLine("异步之外的函数执行3");
13                 act.EndInvoke(asyncResult);

执行效果:

执行效果可以看出,异步线程执行私有的耗时方法,主线程直接执行下面的打印方法,在异步方法执行完毕之后子线程又执行了回调函数。

2,使用Thread方式执行多线程

 1  private Func<T> ThreadWithReturn<T>(Func<T> func) {
 2             T t = default(T);
 3             ThreadStart threadStart = () => {
 4                 func.Invoke();
 5             };
 6             System.Threading.Thread thread = new System.Threading.Thread(threadStart);
 7             thread.Start();
 8             return new Func<T>(() =>{
 9                 thread.Join(); //让当前线程加入到主线程中
10                 return t;
11             });
12         } 

调用:

1  Func<int> funcInvoke = this.ThreadWithReturn<int>(func);
2             Console.WriteLine("执行其他的操作1");
3             System.Threading.Thread.Sleep(1000);
4             Console.WriteLine("执行其他的操作2");
5             System.Threading.Thread.Sleep(1000);
6             Console.WriteLine("执行其他的操作3");
7             Console.WriteLine(funcInvoke.Invoke()); 

3,ThreadPool线程池方式执行多线程

ThreadPool.QueueUserWorkItem(t=>{});   开辟一条线程执行方法函数

实例化ManualResetEvent 类,通过实例化对象调用Set() ,Reset()  ,waiteOne() 方法等待ManualResetEvent对象变成true时才会执行下面的方法。

 1  private void ThreadPool_Click(object sender, EventArgs e)
 2         {
 3             //线程池
 4             {
 5                 Console.WriteLine($"-------线程池执行开始------ {System.Threading.Thread.CurrentThread.ManagedThreadId}");
 6                 ManualResetEvent mre = new ManualResetEvent(false); //设置线程池运行信号量,传递false代表关闭状态
 7                 ThreadPool.QueueUserWorkItem(t =>
 8                 {
 9                     Console.WriteLine("t的值是:"+t);
10                     this.DoSomethingLong("ThreadPool_Click");
11                     Console.WriteLine("子线程的线程ID是:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
12                     mre.Set(); //打开
13                                //mre.Reset();//关闭
14                 });
15                 mre.WaitOne(); //等待所有线程执行完毕再执行下面的逻辑,会卡住页面线程
16             }
17
18             //ThreadPool.SetMaxThreads(8, 8); //设置最大工作线程数量和IO线程数量。
19             //ThreadPool.SetMinThreads(8, 8);
20             #region ManualResetEvent
21             {
22                 ManualResetEvent mre = new ManualResetEvent(false);  //初始化关闭
23                 System.Threading.ThreadPool.QueueUserWorkItem(t =>
24                 {
25                     System.Threading.Thread.Sleep(2000);
26                     Console.WriteLine("第一次执行线程暂停2000ms");
27                     mre.Set();//打开
28                 });
29                 mre.WaitOne();
30                 mre.Reset();//关闭
31                 new Action(() =>
32                 {
33                     System.Threading.Thread.Sleep(2000);
34                     Console.WriteLine("第二次执行线程暂停2000ms");
35                     mre.Set();
36                 }).BeginInvoke(null, null);
37                 mre.WaitOne();
38             }
39             #endregion
40             Console.WriteLine($"-------线程池执行结束------ {System.Threading.Thread.CurrentThread.ManagedThreadId}");
41         }

4,Task方式执行多线程

Task.Factory.StartNew(() => { this.DoSomethingLong(name); });   开辟一条新的执行线程

ContinueWhenAll和ContinueWhenAny都是异步方式执行的调用,都不会卡主线程。

Task.Factory.ContinueWhenAll(taskList.ToArray(),tList=>{doCallBack。。。});//所有任务执行完成之后再调用回调函数。

Task.Factory.ContinueWhenAny(taskList.ToArray(),t=>{doCallBack。。。});//任意一个任务执行完成之后再调用回调函数。

WaiteAll和WaiteAny都是同步方式执行的调用,都会卡住主线程。

Task.WaiteAll(taskList.ToArray()); //所有任务完成后再执行后面的代码,会卡主线程

Task.WaiteAny(taskList.ToArray()); //任意任务完成后再执行后面的代码,会卡主线程

 1 private void Task_Click(object sender, EventArgs e)
 2         {
 3             Console.WriteLine();
 4             Console.WriteLine();
 5             Console.WriteLine($"------------Task 执行开始 当前线程是:{System.Threading.Thread.CurrentThread.ManagedThreadId}----------");
 6             List<Task> taskList = new List<Task>();
 7             for (int i = 0; i < 5; i++)
 8             {
 9                 string name = string.Format("Task_Click"+i);
10                Task taskNew =  Task.Factory.StartNew(() => {
11                     this.DoSomethingLong(name);
12                 });
13                 taskList.Add(taskNew);
14             }
15             //等待所有任务都完成再调用回调方法,不会卡主线程
16             //Task.Factory.ContinueWhenAll(taskList.ToArray(), tList =>
17             //{
18             //    Console.WriteLine($"所有任务都执行完毕后调用的回调方法{System.Threading.Thread.CurrentThread.ManagedThreadId}");
19             //});
20
21             //任意一个任务执行完成就调用,不会卡主线程
22             //Task.Factory.ContinueWhenAny(taskList.ToArray(), t =>
23             //{
24             //    Console.WriteLine(t);
25             //    Console.WriteLine($"任意一个任务执行完毕后调用的回调方法{System.Threading.Thread.CurrentThread.ManagedThreadId}");
26             //});
27
28              Task.WaitAll(taskList.ToArray());   //等待所有任务完成会卡主线程
29             // Task.WaitAny(taskList.ToArray());   //等待任意一个任务完成
30
31             Console.WriteLine($"------------Task 执行结束 当前线程是:{System.Threading.Thread.CurrentThread.ManagedThreadId}----------");
32         }

5,异常处理,线程取消,多线程的临时变量和线程安全 lock

  1 /// <summary>
  2         /// 异常处理,线程取消,多线程的临时变量和线程安全 lock
  3         /// </summary>
  4         /// <param name="sender"></param>
  5         /// <param name="e"></param>
  6         private void ThreadCore_Click(object sender, EventArgs e)
  7         {
  8             List<Task> taskList = new List<Task>();
  9
 10             try
 11             {
 12                 #region 线程中的异常处理
 13                 //for (int i = 0; i < 20; i++)
 14                 //{
 15                 //    string name = string.Format($"ThreadCore_Click_{i}");
 16                 //    Action<object> act = t =>
 17                 //    {
 18                 //        try
 19                 //        {
 20                 //            System.Threading.Thread.Sleep(1000);
 21                 //            if (t.Equals("ThreadCore_Click_11"))
 22                 //            {
 23                 //                throw new Exception("ThreadCore_Click_11_Exception");
 24                 //            }
 25                 //            if (t.Equals("ThreadCore_Click_12"))
 26                 //            {
 27                 //                throw new Exception("ThreadCore_Click_12_Exception");
 28                 //            }
 29                 //            Console.WriteLine($"{name} ,执行成功!");
 30                 //        }
 31                 //        catch (Exception ex)
 32                 //        {
 33                 //            //在线程Action加try catch,记录日志,不抛异常。
 34                 //        }
 35                 //    };
 36                 //    taskList.Add(Task.Factory.StartNew(act, name));
 37                 //}
 38                 //Task.WaitAll(taskList.ToArray());  //加上WaitAll
 39                 #endregion
 40
 41                 #region 线程取消
 42                 // 线程间通信都是通过共有变量:都能访问局部变量/全局变量,数据库值,硬盘文件
 43                 //CancellationTokenSource cts = new CancellationTokenSource();  //线程是否取消,用信号量标记
 44
 45                 //for (int i = 0; i < 40; i++)
 46                 //{
 47                 //    string name = string.Format($"ThreadCore_Click{i}");
 48                 //    Action<object> act = t =>
 49                 //    {
 50                 //        try
 51                 //        {
 52                 //            System.Threading.Thread.Sleep(2000);
 53                 //            Console.WriteLine($"当前线程为:{System.Threading.Thread.CurrentThread.ManagedThreadId}");
 54                 //            if (t.Equals("ThreadCore_Click11"))
 55                 //            {
 56                 //                throw new Exception("ThreadCore_Click11 执行失败");
 57                 //            }
 58                 //            if (t.Equals("ThreadCore_Click12"))
 59                 //            {
 60                 //                throw new Exception("ThreadCore_Click12 执行失败");
 61                 //            }
 62                 //            if (cts.IsCancellationRequested) //查看当前线程是否已经被取消
 63                 //            {
 64                 //                Console.WriteLine("取消执行" + t);
 65                 //            }
 66                 //            else
 67                 //            {
 68                 //                Console.WriteLine("执行成功" + t);
 69                 //            }
 70                 //        }
 71                 //        catch (Exception ex)
 72                 //        {
 73                 //            cts.Cancel();//出现异常设置未执行的线程取消。
 74                 //            throw;
 75                 //        }
 76                 //    };
 77                 //    taskList.Add(Task.Factory.StartNew(act, name, cts.Token));  //将 cts.Token 传递到执行线程中用以判断
 78                 //}
 79                 //Task.WaitAll(taskList.ToArray());   //必须添加
 80                 #endregion
 81
 82                 #region 多线程临时变量
 83                 //for (int i = 0; i < 5; i++)
 84                 //{
 85                 //    int k = i;
 86                 //    new Action(()=> {
 87                 //        System.Threading.Thread.Sleep(100);
 88                 //        //Console.WriteLine(i);
 89                 //        Console.WriteLine(k);
 90                 //    }).BeginInvoke(null,null);
 91                 //}
 92                 #endregion
 93
 94                 #region 线程安全
 95                 for (int i = 0; i < 10000; i++)
 96                 {
 97                     int newI = i;
 98                    taskList.Add(Task.Factory.StartNew(() =>
 99                     {
100                         lock (threadLock) //lock后面的方法块任意时刻只有一个线程进来,此时就变成了单线程。
101                         {
102                             IntTotal += 1;
103                         }
104                     }));
105                 }
106                 Task.WaitAll(taskList.ToArray());
107                 Console.WriteLine($"IntTotal:{IntTotal}");
108                 IntTotal = 0;
109                 #endregion
110             }
111             catch (AggregateException ex)
112             {
113                 foreach (var item in ex.InnerExceptions)
114                 {
115                     Console.WriteLine($"异常信息为:" + item.Message);
116                 }
117             }
118             catch (Exception ex)
119             {
120                 throw;
121             }
122         }
时间: 2024-08-25 06:23:20

8异步和多线程的相关文章

C#中异步和多线程的区别

C#中异步和多线程的区别是什么呢?异步和多线程两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性.甚至有些时候我们就认为异步和多线程是等同的概念.但是,异步和多线程还是有一些区别的.而这些区别造成了使用异步和多线程的时机的区别. 异步和多线程的区别之异步操作的本质 所有的程序最终都会由计算机硬件来执行,所以为了更好的理解异步操作的本质,我们有必要了解一下它的硬件基础. 熟悉电脑硬件的朋友肯定对DMA这个词不陌生,硬盘.光驱的技术规格中都有明确DMA的模式指标,其实网卡.声卡.显卡也是有

同步、异步、多线程与事件型综述

转自:http://blog.csdn.net/chszs/article/details/8867174 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs首先要了解什么是阻塞和阻塞式IO.线程在执行中如果遇到磁盘读写或网络通信(统称IO操作),通常要耗费较长的时间,这时操作系统会剥夺此线程的CPU控制权,使其暂停执行,同时将资源让给其他的工作线程,这种线程调度方式称为阻塞.当IO操作完毕时,操作系统将这个线程的阻塞状态解除,恢复其对CPU的控制权,令

PHP中实现异步调用多线程程序代码

本文章详细的介绍了关于PHP中实现异步调用多线程方法,下面我们以给1000个用户发送一封推荐邮件,用户输入或者导入邮件账号了提交服务器执行发送来讲述. 比如现在有一个场景,给1000个用户发送一封推荐邮件,用户输入或者导入邮件账号了提交服务器执行发送 第一种解决方法: 代码如下: <?php $count=count($emailarr); for($i=0;$i<$count;$i ) { sendmail(.....);//发送邮件 } ?>              这段代码用户体

关于异步和多线程的关系

个人的理解是这样的: 1.  异步通信的意思是,当A发送完消息之后,不等待B的回应,继续执行之后的程序.在将来的某个时刻,A再来检查是否收到B的回应. 异步就是彼此独立,在等待某事件的过程中继续做自己的事,不需要等待这一事件完成后再工作. 2. 多线程是程序设计的逻辑层概念,它是进程中并发运行的一段代码.多线程可以实现线程间的切换执行. 3. 异步和同步是相对的,同步就是顺序执行,执行完一个再执行下一个,需要等待.协调运行.线程就是实现异步的一个方式.异步是让调用方法的主线程不需要同步等待另一线

并发和并行,异步与多线程区别

1.并发和并行的区别 可由上图形象指出两者的区别: 1)定义: 并发:在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行. 并行:在操作系统中,一组程序按独立异步的速度执行,无论从微观还是宏观,程序都是一起执行的. 来个比喻:并发和并行的区别就是一个人同时吃三个馒头和三个人同时吃三个馒头: 在单CPU系统中,系统调度在某一时刻只能让一个线程运行,虽然这种调试机制有多种形式(大多数是时间片轮巡为主

IOS异步和多线程操作&amp;&amp;在sqlite3中的应用

1,数据库I/O操作(异步) 数据库本身是存储在磁盘上.访问和修改数据库,即对磁盘进行读写,即I/O操作. 磁盘属于计算机硬件,具有DMA能力,不需要CPU干预,可以实现异步操作. I/O操作一般是消耗时间,sqlite使用异步处理I/O操作. 当有多个事务对数据库进行操作,对应,也会有多个I/O操作. 操作系统将I/O操作,合理放入一个I/O队列.一次性将队列内的I/O操作提交给磁盘系统,并行处理多个I/O,提高效率.本人也没有特别深入研究. 2,异步和多线程 异步和多线程,都有能力实现,不阻

程序优化方案(一) 代码优化之异步、多线程、缓存

上部分说了代码的合并,那么接下来就说说如何真正的提升程序的速度.这里不得不提到的几个优化程序速度的技术就是异步,多线程和缓存.首先我们要知道程序为什么会卡,特别是加载的时候很慢,原因在于之前的程序是单线程,中途大量的数据库操作和外部接口的调用都耗用了大量的时间导致方法堵塞,所以界面上表现的就是假死状态. 那么异步加多线程加缓存用对地方刚好可以解决这些问题,那么这三种东西都是在什么情况下使用呢. 一.异步 假如现在我们主程序上有一个Grid,当我们在加载的时候这个Grid需要绑定大量的数据,并且根

异步、多线程解惑

关于多线程和异步相信不少人都有疑问,它们之间到底有什么区别呢? 从知乎上看见一个比喻还是比较好理解的: 现在假设整个城市就只有1个火车,1个售票员,每个乘客咨询售票员后需要思考1分钟再决定买哪趟车的票. 异步 在买票的人咨询后,需要思考1分钟,马上靠边站,但不用重新排队,什么时候想清楚可以立马去跟售票员去买票.在该人站在旁边思考的时候,后面的人赶紧上去接着买.这时候队伍是很快的挪动的,没有阻塞,售票员的最大化的效率. 多线程 火车站开n个窗口(但还是只有一个人售票),外面同时排n个队,售票员回答

异步与多线程的区别

当我们在遇到需要长时间执行的任务时候,比如读取一个文件,远程服务调用.这些功能都会阻塞主线程,造成主线程卡死,从而造成一种软件崩溃的假象.这样的情况下,我们都会想到使用异步多线程的技术去解决这个问题. 我在学习NodeJs的之前,一直以为异步和多线程是同一个概念,当我接触到Node的时候,感觉自己遭到了当头棒喝,Node是单线程的,也不支持多线程,但是他的很多操作都是异步的,比如文件的读取.这让我很沮丧,也花了很长时间去理解异步和多线程的概念区别,现在记录下来我现在的想法,希望看到的朋友也能帮组

Threads(异步和多线程)

原文:Threads(异步和多线程) Task是.NET Framework3.0出现的,线程是基于线程池的,然后提供丰富的api,Thread方法很多很强大,但是太过强大,没有限制. DoSomethingLong方法如下: /// <summary> /// 一个比较耗时耗资源的私有方法 /// </summary> /// <param name="name"></param> private void DoSomethingLon