iT邦幫忙

2021 iThome 鐵人賽

DAY 29
2
Software Development

C# 入门系列 第 29

C#入门之异步编程

在很多情况下,我们的任务前后之间没有必然的联系的,所以我们可以不需要等待前面命令结束,才开始后面的任务。我们可以多个任务并行运行,这就是异步编程。

首先我们先来看一个常规的程序:

using System;
using System.Diagnostics;
using System.Linq;
using System.Net.NetworkInformation;

namespace ConsoleApp30
{
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch stopwatch = Stopwatch.StartNew();    // 统计程序运行的时间
            Ping ping = new Ping();
            String NetNumber = "192.168.0.";
            int[] HosNumer = Enumerable.Range(1, 254).ToArray();
            foreach( int i in HosNumer )
            {
                string IP = NetNumber + i;
                PingReply pingReply = ping.Send($"{IP}");
                if(pingReply.Status == IPStatus.Success)
                {
                    Console.WriteLine($"The IP {IP} ping is pass.");
                }
                else
                {
                    Console.WriteLine($"The IP {IP} ping is failed.");
                }
            }
            Console.WriteLine($"Time is {stopwatch.ElapsedMilliseconds}");
        }
    }
}

这是一个 ping 程序,它会 ping 指定的 IP 的地址的状态,并返回结果。

运行结果:

The IP 192.168.0.1 ping is pass.
The IP 192.168.0.2 ping is failed.
The IP 192.168.0.3 ping is failed.
The IP 192.168.0.4 ping is failed.
The IP 192.168.0.5 ping is failed.
......
......
The IP 192.168.0.252 ping is failed.
The IP 192.168.0.253 ping is failed.
The IP 192.168.0.254 ping is failed.
Time is 751872     // 程序运行的时间

使用异步的方式:

using System;
using System.Diagnostics;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading.Tasks;

namespace ConsoleApp30
{
    class Program
    {
        static async Task Main(string[] args)   // 这里要使用 async
        {
            Stopwatch stopwatch = Stopwatch.StartNew();    // 统计程序运行的时间
            Ping ping = new Ping();
            String NetNumber = "192.168.0.";
            int[] HosNumer = Enumerable.Range(1, 254).ToArray();
            foreach( int i in HosNumer )
            {
                string IP = NetNumber + i;
                 // 添加 await, 并且使用 ping 的方式也有所不同
                PingReply pingReply = await ping.SendPingAsync($"{IP}");  
                if(pingReply.Status == IPStatus.Success)
                {
                    Console.WriteLine($"The IP {IP} ping is pass.");
                }
                else
                {
                    Console.WriteLine($"The IP {IP} ping is failed.");
                }
            }
            Console.WriteLine($"Time is {stopwatch.ElapsedMilliseconds}");
        }
    }
}

运行结果:

The IP 192.168.0.1 ping is pass.
The IP 192.168.0.2 ping is failed.
The IP 192.168.0.3 ping is failed.
The IP 192.168.0.4 ping is failed.
The IP 192.168.0.5 ping is failed.
......
......
The IP 192.168.0.250 ping is failed.
The IP 192.168.0.251 ping is failed.
The IP 192.168.0.252 ping is failed.
The IP 192.168.0.253 ping is failed.
The IP 192.168.0.254 ping is failed.
Time is 438322

这次测试,所花费的时间,比之前少了很多。


上一篇
C# 入门之函数重载
下一篇
C#入门之类(补充)
系列文
C# 入门32

2 則留言

0
胭脂虎
iT邦新手 2 級 ‧ 2021-09-29 20:10:08

我每天都見您慢慢更新,加油加油! XD

as900 iT邦研究生 5 級 ‧ 2021-09-30 09:43:24 檢舉

一直在补前面的/images/emoticon/emoticon28.gif

1
deh
iT邦新手 2 級 ‧ 2021-11-29 16:06:11
 PingReply pingReply = await ping.SendPingAsync($"{IP}");  

這樣結果其實跟同步沒什麼不同
都是要等待結果後才能做其他事

非同步可能像下面這樣會比較有感

    var pingReplyTask = ping.SendPingAsync($"{IP}"); // 0:00 假設這Method要花上10秒才能取得結果
    Other Code......//0:00~0:10 等待結果期間可以做其他事情    
    PingReply pingReply = await pingReplyTask;//0:10 取得結果

這個例子做成非同步會是像這樣

using System;
using System.Diagnostics;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading.Tasks;
using System.Collections.Generic;

namespace ConsoleApp30
{
    class Program
    {
        static async Task Main(string[] args)   // 这里要使用 async
        {
            Stopwatch stopwatch = Stopwatch.StartNew();    // 统计程序运行的时间
            
            String NetNumber = "127.0.0.";
            int[] HosNumer = Enumerable.Range(1, 254).ToArray();
            List<Task> tasks = new List<Task>();
            foreach (int i in HosNumer)
            {
                tasks.Add(Task.Run(async () =>
                {
                    string IP = NetNumber + i;
					Ping ping = new Ping();
                    // 添加 await, 并且使用 ping 的方式也有所不同
                    PingReply pingReply = await ping.SendPingAsync($"{IP}");
                    if (pingReply.Status == IPStatus.Success)
                    {
                        Console.WriteLine($"The IP {IP} ping is pass.");
                    }
                    else
                    {
                        Console.WriteLine($"The IP {IP} ping is failed.");
                    }
                }));
            }
            Task.WaitAll(tasks.ToArray());
            Console.WriteLine($"Time is {stopwatch.ElapsedMilliseconds}");
        }
    }
}

但由於非同步的Method本來就很快了 沒什麼要等的 所以基本上沒差

我要留言

立即登入留言