C#之同步、异步、多线程

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/>");

    }
发布了19 篇原创文章 · 获赞 6 · 访问量 9432

猜你喜欢

转载自blog.csdn.net/u012712556/article/details/79368897
今日推荐