C#之同步、异步、多线程
2018-02-25 14:58
211 查看
C#之同步、异步、多线程
今天我们来一起学习C#中的同步。异步以及多线程。在学习这些之前,我们先来简单地了解下进程和线程之间的关系,一个应用程序即一个进程,而一个进程的执行需要多个线程来辅助,所以运行一个进程后,会运行多个线程。所谓的同步,即按照代码的顺序执行,也就是用同一个线程来执行所有的操作。而在执行异步操作时,会启动多个线程来执行各个操作,并且他们开启的顺序以及执行的时间各不相同,具体的区别我们在代码中进行比较。我们新建一个基于.Net 4.0的网站,并添加一个页面,并在页面中添加U两个按钮,分别用来执行同步操作和异步操作。
1 同步、异步对比
同步非诚容易理解,我们通常执行的代码就是用同步来操作了,即用主线程来按顺序执行所有操作,但异步就不同了,对于不同的操作,是通过开启一个新线程来执行的。
在C#中,异步是基于委托来实现的。然后通过委托的
BeginInvoke()l来开启一个新线程,然后用这个新线程来执行这个委托中方法。
该方法需要三个参数,第一个是委托方法需要的参数,第二个是该线程执行完成后的回调方法,它是一个AsyncCallback类型的委托,第三个参数是一个状态值。该方法返回一个IAsyncResult类型的变量,该变量可用于执行EndInvoke()参数
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> </head> <body> <form id="form1" runat="server"> <div> <asp:Button ID="Button1" runat="server" Text="同步" OnClick="Button1_Click"/> <asp:Button ID="Button2" runat="server" Text="异步" OnClick="Button2_Click" /> <asp:Button ID="Button3" runat="server" Text="Task" OnClick="Button3_Click" /> </div> </form> </body> </html>
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Threading; using System.Threading.Tasks; public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { Response.Write("同步异步"); } } public long DoSomething(string name) { Response.Write(DateTime.Now.ToString("hh:mm:ss.fff") + name + "开始执行DoSomething 当前线程Id:" + Thread.CurrentThread.ManagedThreadId + "<br/>"); long result = 0; for (int i = 0; i < 100000000; i++) result += i; Thread.Sleep(2); Response.Write(DateTime.Now.ToString("hh:mm:ss.fff") + name + "结束执行DoSomething 当前线程Id:" + Thread.CurrentThread.ManagedThreadId + "结算结果" + result + "<br/>"); return result; } //同步 protected void Button1_Click(object sender, EventArgs e) { Response.Write("*********************************************************************************************************************<br/>"); Response.Write(DateTime.Now.ToString("hh:mm:ss.fff ") + "开始执行同步 当前线程" + Thread.CurrentThread.ManagedThreadId + "<br/>"); for (int i = 0; i < 5; i++) { string name = string.Format("同步_{0}", i); //同步调用 用主线程去处理该操作 同步运行速度较慢 不占用过多的系统资源 同步按顺序执行 DoSomething(name); //无返回值的 } Response.Write(DateTime.Now.ToString("hh:mm:ss.fff ") + "结束执行同步 当前线程" + Thread.CurrentThread.ManagedThreadId + "<br/>"); Response.Write("*********************************************************************************************************************<br/>"); } //异步 protected void Button2_Click(object sender, EventArgs e) { Response.Write("*********************************************************************************************************************<br/>"); Response.Write(DateTime.Now.ToString("hh:mm:ss.fff ") + "开始执行异步 当前线程" + Thread.CurrentThread.ManagedThreadId + "<br/>"); // Action<string> method = DoSomething;//无返回值 Func<string, long> method = DoSomething; //有返回值 AsyncCallback callback = (result) => { Response.Write("执行callback " + result.AsyncState + "<br/>"); //实例化回调方法的委托 // long iResult = method.EndInvoke(result); //每个线程只能有一个EndInvoke 卡主子线程 }; for (int i = 0; i < 5; i++) { string name = string.Format("异步_{0}", i); // doSomethingMethod.Invoke(name); IAsyncResult iResult = method.BeginInvoke(name, callback, "abc"); //异步调用 启动多个线程 运行速度快 占用更多的系统资源 异步执行顺序是随机的 //线程的请求分配是随机的 运行同一任务的时间也不同 // long result = method.EndInvoke(iResult); //获取异步调用的返回值 //会卡主线程 等待异步完成 //while(! iResult.IsCompleted) //{ // Response.Write("请等待 .............."); // Thread.Sleep(100); //主线程等待 //} } Response.Write(DateTime.Now.ToString("hh:mm:ss.fff ") + "结束执行异步 当前线程" + Thread.CurrentThread.ManagedThreadId + "<br/>"); Response.Write("*********************************************************************************************************************<br/>"); } }
2 Task
在C#中启动新线程有两种方法,第一个是通过委托的BeginInvoke方法来实现,第二个就是通过TaskFactory类来实现,通过该类对象的StartNew()方法来启动一个新线程,该方法需要一个Action委托类型的参数,标识该线程要执行的参数,且该方法返回一个Task类的对象。其中TaskFactory类的ContinueWhenAll()可用于在某些线程执行完成后要执行的操作,该方法需要一个Task[]类型的参数,包含了所有要监视的进程。
//Task protected void Button3_Click(object sender, EventArgs e) { Response.Write("*********************************************************************************************************************<br/>"); Response.Write(DateTime.Now.ToString("hh:mm:ss.fff ") + "开始执行操作 当前线程" + Thread.CurrentThread.ManagedThreadId + "<br/>"); Response.Write("接项目<br/>"); Response.Write("谈价格<br/>"); Response.Write("需求分析<br/>"); Response.Write("定金<br/>"); Action action1 = () => Coding("Jack", "Portal"); //实例化几个用于多线程的委托 Action action2 = () => Coding("Bob", "WeiChat"); Action action3 = () => Coding("Andt", "BackOffice"); TaskFactory taskFactory = new TaskFactory(); //实例化一个多线程 List<Task> taskList = new List<Task>(); taskList.Add(taskFactory.StartNew(action1)); //创建并执行多个线程 taskList.Add(taskFactory.StartNew(action2)); taskList.Add(taskFactory.StartNew(action3)); //之前的多线程完成后 启动一个新线程 Task taskMerge = taskFactory.ContinueWhenAll(taskList.ToArray(), (tList) => { Response.Write("合成 线程id: " + Thread.CurrentThread.ManagedThreadId + "<br/>"); }); //等待某个线程结束 Task.WaitAny(taskList.ToArray()); Response.Write("测试<br/>"); Response.Write("收20%<br/>"); // taskList.Add(taskMerge); //等执行合并操作到的线程结束 Task.WaitAll(new Task[] {taskMerge}); Response.Write("验收<br/>"); Response.Write("收钱<br/>"); Response.Write(DateTime.Now.ToString("hh:mm:ss.fff ") + "结束执行操作 当前线程" + Thread.CurrentThread.ManagedThreadId + "<br/>"); Response.Write("*********************************************************************************************************************<br/>"); }
相关文章推荐
- C#.net同步异步SOCKET通讯和多线程总结(5)tcp发送和接受的代码
- C#.net同步异步SOCKET通讯和多线程总结
- C#.net同步异步SOCKET通讯和多线程总结
- C#.net同步异步SOCKET通讯和多线程总结
- C#同步 异步 多线程的联系和区别
- C#.net同步异步SOCKET通讯和多线程总结
- C#.net同步异步SOCKET通讯和多线程总结2
- C#.net同步异步SOCKET通讯和多线程总结
- iOS中多线程知识总结:进程、线程、GCD、串行队列、并行队列、全局队列、主线程队列、同步任务、异步任务等
- 并发 并行 同步 异步 多线程的区别
- C#中多线程和异步的区别
- 在.Net框架中 C# 实现多线程的同步方法详解
- C#多线程与异步的区别
- 多线程 同步异步锁 单列
- C# 多线程系列之异步回调(委托)
- C#中异步和多线程的区别
- 网络传输之同步异步SOCKET通讯和多线程[转]
- 同步、异步、多线程
- GCD网络多线程---同步运行,异步运行,串行队列,并行队列
- C#同步、异步远程下载文件实例