C#异步和多线程

打开电脑的任务管理器可以发现,每一个程序都是一个进程。所谓进程就是一个程序运行时,占用的全部计算机资源的总和。

线程就是程序执行流的最小单位。任何操作系统都是线程完成的,线程是依托于进程存在的,一个进程可以包含多个线程,线程也可以有自己的计算资源。

同步:完成计算之后,才会进入下一行。异步:不会等待方法的完成,会直接进入下一行。是非阻塞。

 public partial class Form1 : Form
 {
     public Form1()
     {
         InitializeComponent();
     }
     /// <summary>
     /// 异步方法
     /// </summary>
     /// <param name="sender"></param>
     /// <param name="e"></param>
     private void btnAsync_Click(object sender, EventArgs e)
     {
         Console.WriteLine($"*************************************btnAsync_Click Start {Thread.CurrentThread.ManagedThreadId} ");
         //实例化一个委托
         Action<string> action = this.DoSomethingLong;
         //同步的多线程
         action.Invoke("btnAsync_Click1");
         //同步的多线程
         action("btnAsync_Click2");
         //通过委托的异步调用
         action.BeginInvoke("btnAsync_Click3", null, null);
         Console.WriteLine($"*************************************btnAsync_Click End {Thread.CurrentThread.ManagedThreadId} ");
     }

     /// <summary>
     /// 一个比较耗时耗资源的私有方法。 
     /// </summary>
     /// <param name="name"></param>
     private void DoSomethingLong(string name)
     {
         Console.WriteLine($"*************************************DoSomethingLong Start{Thread.CurrentThread.ManagedThreadId} ");
         Console.WriteLine($"hell world ");
         Console.WriteLine($"*************************************DoSomethingLong End{Thread.CurrentThread.ManagedThreadId} ");
     }
     /// <summary>
     /// 同步方法
     /// </summary>
     /// <param name="sender"></param>
     /// <param name="e"></param>
     private void btnSync_Click(object sender, EventArgs e)
     {
         Console.WriteLine($"*************************************btnSync_Click Start {Thread.CurrentThread.ManagedThreadId} ");
         int j = 3;
         int k = 5;
         int m = j + k;
         for (int i = 0; i < 5; i++)
         {
             string name = string.Format($"btnSync_Click{i}");
             this.DoSomethingLong(name);
         }

         Console.WriteLine($"*************************************btnSync_Click End {Thread.CurrentThread.ManagedThreadId} ");
     }
 }

 public Form1()
 {
     InitializeComponent();
 }
/// <summary>
/// 异步方法
/// 1 同步方法卡界面: 主线程也叫UI线程,在启动界面时就已经分配好了,忙于计算就不能执行其它的了
/// 异步多线程方法不卡界面,主线程完事了,计算任务交给子线程。
/// 2 异步多线程方法快,因为多个线程并发运算;多个独立任务可以同时运行。
/// 3 异步多线程无序:启动无序,执行时间不确定,结束也无序;
/// 4 
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnAsync_Click(object sender, EventArgs e)
{
    Console.WriteLine($"*************************************btnAsync_Click Start {Thread.CurrentThread.ManagedThreadId} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
    ////实例化一个委托
    //Action<string> action = this.DoSomethingLong;
    ////同步的多线程
    //action.Invoke("btnAsync_Click1");
    ////同步的多线程
    //action("btnAsync_Click2");
    ////通过委托的异步调用
    //action.BeginInvoke("btnAsync_Click3", null, null);

    Action<string> action = this.DoSomethingLong;
    for (int i = 0; i < 5; i++)
    {
        string name = string.Format($"btnAsync_Click{i}");
        action.BeginInvoke(name, null, null);
    }            

    Console.WriteLine($"*************************************btnAsync_Click End {Thread.CurrentThread.ManagedThreadId} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
}

/// <summary>
/// 一个比较耗时耗资源的私有方法。 
/// </summary>
/// <param name="name"></param>
private void DoSomethingLong(string name)
{
    Console.WriteLine($"*************************************DoSomethingLong Start{Thread.CurrentThread.ManagedThreadId} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
    long lResult = 0;
    for (int i = 0; i < 1000000; i++)
    {
        lResult += i;
    }
    Console.WriteLine($"DoSomethingLong {name}");
    Thread.Sleep(2000);
    Console.WriteLine($"*************************************DoSomethingLong End{Thread.CurrentThread.ManagedThreadId} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
}
/// <summary>
/// 同步方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSync_Click(object sender, EventArgs e)
{
    Console.WriteLine($"*************************************btnSync_Click Start {Thread.CurrentThread.ManagedThreadId} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
    int j = 3;
    int k = 5;
    int m = j + k;
    for (int i = 0; i < 5; i++)
    {
        string name = string.Format($"btnSync_Click{i}");
        this.DoSomethingLong(name);
    }

    Console.WriteLine($"*************************************btnSync_Click End {Thread.CurrentThread.ManagedThreadId} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
}
/// <summary>
/// 异步进阶
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnAsyncAdvanced_Click(object sender, EventArgs e)
{
    Console.WriteLine($"*************************************btnAsyncAdvanced_Click Start {Thread.CurrentThread.ManagedThreadId} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
    //实例化一个委托
    Action<string> act = this.DoSomethingLong;

    IAsyncResult asyncResult = null;
    AsyncCallback callback = ia =>
    {
        //Console.WriteLine(object.ReferenceEquals(asyncResult, ia)); //比较是否相等
        //Console.WriteLine(ia.AsyncState);  //返回BeginInvoke的第三个参数
        //Console.WriteLine("到这里计算已经完成了。");
    };
    //将BeginInvoke运行的返回值asyncResult传给callback回调函数去执行
    asyncResult = act.BeginInvoke("btnAsyncAdvanced_Click", callback, "hello");
    /*
                        int i = 0;
                        while (! asyncResult.IsCompleted)
                        {               
                            if (i<10)
                            {
                                Console.WriteLine($"文件上传完成 {i++ *10}%...");
                            }
                            else
                            {
                                Console.WriteLine($"文件上传完成99.9%...");
                            }
                            Thread.Sleep(200);
                        }
                        Console.WriteLine($"文件上传完成");
            */

    /*
                       Thread.Sleep(200);
                       Console.WriteLine($"Do Something Else......");
                       Console.WriteLine($"Do Something Else......");
                       Console.WriteLine($"Do Something Else......");
                       Console.WriteLine($"Do Something Else......");
                       asyncResult.AsyncWaitHandle.WaitOne(); //以信号量的方式等待任务的完成。
             */
    Func<int> fuc = () =>
    {
        Thread.Sleep(2000);
        return DateTime.Now.Day;
    };
    Console.WriteLine($"fuc.Invoke()={fuc.Invoke()}");

    IAsyncResult asyRest = fuc.BeginInvoke(r =>
                                           {
                                               Console.WriteLine(r.AsyncState);
                                           }, "hello world");
    Console.WriteLine($"fuc.EndInvoke()={fuc.EndInvoke(asyRest)}"); //EndInvok可以等待还可以获取返回值。

    Console.WriteLine($"*************************************btnAsyncAdvanced_Click End {Thread.CurrentThread.ManagedThreadId} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
}

多线程中临时变量的使用,如下列图片中name的不同用法就是临时变量的用法。

多线程中的等待,此时的等待,主线程是处于顺序,主线程会卡界面。用于顺序的完成。

多线程中顺序完成,主线程不会卡界面。用于顺序的完成

多线程不卡主线程等待完成的常用方式。



转载请注明出处:  https://www.cntworld.cn
智能工控 » C#异步和多线程

发表回复

提供最优质的资源集合

立即查看 了解详情