最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

在C#中實(shí)現(xiàn)異步通信的方法步驟

 更新時(shí)間:2026年01月15日 08:39:55   作者:工業(yè)程序猿老趙  
C# 的異步通信基于 async/await 模式,其底層依賴Task和Task<TResult>類型來(lái)封裝異步操作,本文給大家介紹了在C#中實(shí)現(xiàn)異步通信的方法步驟,需要的朋友可以參考下

一、C# 異步通信的核心基礎(chǔ)

C# 的異步通信基于 async/await 模式(這是.NET 4.5 及以上版本推薦的異步編程模型,簡(jiǎn)化了傳統(tǒng)的回調(diào)地獄問(wèn)題),其底層依賴TaskTask<TResult>類型來(lái)封裝異步操作,核心目標(biāo)是避免阻塞調(diào)用線程(尤其是 UI 線程、主線程),提升程序的并發(fā)處理能力和響應(yīng)性。

1. 核心關(guān)鍵字與類型

  • async:修飾方法,標(biāo)記該方法為異步方法,告知編譯器該方法內(nèi)部包含await表達(dá)式,會(huì)被編譯器重寫為狀態(tài)機(jī)。
    • 異步方法的返回類型通常為Task(無(wú)返回值)、Task<T>(有返回值)、ValueTask/ValueTask<T>(高性能場(chǎng)景,減少堆分配)。
    • 異步方法命名約定:后綴加Async(如ConnectAsync、SendDataAsync)。
  • await:等待異步操作完成,僅能在async修飾的方法中使用
    • 等待期間,當(dāng)前線程會(huì)被釋放,去執(zhí)行其他任務(wù),不會(huì)阻塞。
    • 異步操作完成后,會(huì)從暫停處繼續(xù)執(zhí)行后續(xù)代碼。
  • Task/Task<T>:封裝異步操作的結(jié)果和狀態(tài),代表一個(gè)異步操作的執(zhí)行過(guò)程。

2. 最簡(jiǎn)單的異步方法示例(同步方法改造為異步)

// 同步方法
public string GetSyncData()
{
    // 模擬耗時(shí)操作(如文件讀取、網(wǎng)絡(luò)請(qǐng)求)
    Thread.Sleep(2000);
    return "同步數(shù)據(jù)";
}

// 異步方法(改造后)
public async Task<string> GetAsyncData()
{
    // 用Task.Delay替代Thread.Sleep(異步等待,不阻塞線程)
    await Task.Delay(2000);
    return "異步數(shù)據(jù)";
}

// 調(diào)用異步方法
public async Task CallAsyncMethod()
{
    Console.WriteLine("開(kāi)始調(diào)用異步方法");
    string result = await GetAsyncData(); // 等待異步操作完成,不阻塞當(dāng)前線程
    Console.WriteLine($"異步方法返回結(jié)果:{result}");
}

二、C# 網(wǎng)絡(luò)異步通信(TCP 為例)的核心實(shí)現(xiàn)

網(wǎng)絡(luò)通信是異步通信的典型場(chǎng)景(TCP/UDP/HTTP 等),.NET 提供了豐富的異步 API(后綴為Async,無(wú)需手動(dòng)創(chuàng)建線程,即可實(shí)現(xiàn)高效的異步網(wǎng)絡(luò)通信,核心依賴TcpClient、NetworkStream的異步方法。

核心異步 API(對(duì)應(yīng)工業(yè)級(jí) TCP 客戶端場(chǎng)景)

  1. TcpClient.ConnectAsync():異步連接 TCP 服務(wù)端,替代同步的Connect()
  2. NetworkStream.WriteAsync():異步向網(wǎng)絡(luò)流寫入數(shù)據(jù)(發(fā)送數(shù)據(jù)),替代同步的Write()
  3. NetworkStream.ReadAsync():異步從網(wǎng)絡(luò)流讀取數(shù)據(jù)(接收數(shù)據(jù)),替代同步的Read()
  4. 上述方法均支持傳入CancellationToken,用于取消異步操作(優(yōu)雅終止任務(wù))。

完整實(shí)戰(zhàn):TCP 異步通信(客戶端)

基于async/await實(shí)現(xiàn) TCP 客戶端的異步發(fā)送和接收,延續(xù)工業(yè)級(jí)場(chǎng)景的可靠性設(shè)計(jì):

using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AsyncTcpCommunication
{
    public class AsyncTcpClient : IDisposable
    {
        private TcpClient? _tcpClient;
        private NetworkStream? _networkStream;
        private CancellationTokenSource? _cts; // 用于取消異步接收循環(huán)

        // 連接狀態(tài)
        public bool IsConnected => _tcpClient?.Connected == true && _networkStream != null;

        /// <summary>
        /// 異步連接服務(wù)端
        /// </summary>
        public async Task<bool> ConnectAsync(string serverIp, int serverPort)
        {
            try
            {
                _cts = new CancellationTokenSource();
                _tcpClient = new TcpClient();

                // 異步連接:不阻塞當(dāng)前線程,等待連接完成
                await _tcpClient.ConnectAsync(serverIp, serverPort);
                _networkStream = _tcpClient.GetStream();

                Console.WriteLine("成功連接到服務(wù)端");
                // 啟動(dòng)異步接收循環(huán)(后臺(tái)持續(xù)監(jiān)聽(tīng)數(shù)據(jù),不阻塞主線程)
                _ = ReceiveDataLoopAsync(_cts.Token);

                return true;
            }
            catch (SocketException ex)
            {
                Console.WriteLine($"連接失?。簕ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 異步發(fā)送數(shù)據(jù)
        /// </summary>
        public async Task<bool> SendDataAsync(string message)
        {
            if (!IsConnected || string.IsNullOrEmpty(message))
                return false;

            try
            {
                byte[] sendData = Encoding.UTF8.GetBytes(message);
                // 異步寫入網(wǎng)絡(luò)流:不阻塞當(dāng)前線程,等待數(shù)據(jù)發(fā)送完成
                await _networkStream!.WriteAsync(sendData, 0, sendData.Length);
                await _networkStream.FlushAsync(); // 異步刷新緩沖區(qū)

                Console.WriteLine($"成功發(fā)送數(shù)據(jù):{message}");
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"發(fā)送數(shù)據(jù)失?。簕ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 異步接收數(shù)據(jù)循環(huán)(持續(xù)監(jiān)聽(tīng)服務(wù)端數(shù)據(jù))
        /// </summary>
        private async Task ReceiveDataLoopAsync(CancellationToken cancellationToken)
        {
            if (!IsConnected)
                return;

            byte[] buffer = new byte[1024]; // 接收緩沖區(qū)
            try
            {
                while (!cancellationToken.IsCancellationRequested && IsConnected)
                {
                    // 異步讀取網(wǎng)絡(luò)流:無(wú)數(shù)據(jù)時(shí)掛起,不阻塞線程,有數(shù)據(jù)時(shí)恢復(fù)執(zhí)行
                    int receivedBytes = await _networkStream!.ReadAsync(buffer, 0, buffer.Length, cancellationToken);

                    if (receivedBytes == 0)
                    {
                        Console.WriteLine("服務(wù)端主動(dòng)關(guān)閉連接");
                        break;
                    }

                    // 解析接收到的數(shù)據(jù)
                    string receivedMessage = Encoding.UTF8.GetString(buffer, 0, receivedBytes);
                    Console.WriteLine($"接收到服務(wù)端數(shù)據(jù):{receivedMessage}");
                }
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("接收循環(huán)已被取消");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"接收數(shù)據(jù)異常:{ex.Message}");
            }
        }

        /// <summary>
        /// 釋放資源
        /// </summary>
        public void Dispose()
        {
            _cts?.Cancel(); // 取消異步接收循環(huán)
            _networkStream?.Dispose();
            _tcpClient?.Dispose();
            Console.WriteLine("已斷開(kāi)連接并釋放資源");
        }
    }

    // 調(diào)用示例
    class Program
    {
        static async Task Main(string[] args)
        {
            using var tcpClient = new AsyncTcpClient();

            // 異步連接(不阻塞Main線程)
            bool isConnected = await tcpClient.ConnectAsync("127.0.0.1", 8888);
            if (!isConnected)
                return;

            // 循環(huán)異步發(fā)送數(shù)據(jù)
            int sendCount = 0;
            while (tcpClient.IsConnected)
            {
                sendCount++;
                string message = $"異步通信測(cè)試 {sendCount} - {DateTime.Now:HH:mm:ss}";
                await tcpClient.SendDataAsync(message);

                // 異步等待3秒,不阻塞線程
                await Task.Delay(3000);
            }
        }
    }
}

三、異步通信的關(guān)鍵特性與注意事項(xiàng)

  1. await的非阻塞特性
  • await等待異步操作時(shí),不會(huì)阻塞當(dāng)前線程,線程會(huì)被釋放回線程池,去處理其他任務(wù)(如其他請(qǐng)求、UI 事件)。
  • 只有異步操作完成后,才會(huì)在合適的線程上恢復(fù)執(zhí)行await后續(xù)的代碼,這是提升程序并發(fā)能力的核心。
  1. 避免 “異步同步化”(常見(jiàn)坑)
  • 不要在異步方法中使用Task.Wait()、Task.Result(同步等待),這會(huì)導(dǎo)致線程阻塞,甚至引發(fā)死鎖(尤其是在 UI 線程、ASP.NET Core 環(huán)境中)。
  • 錯(cuò)誤示例:var result = GetAsyncData().Result;(阻塞線程)
  • 正確示例:var result = await GetAsyncData();(非阻塞等待)
  1. CancellationToken的使用
  • 用于優(yōu)雅取消異步操作(如停止 TCP 接收循環(huán)、中斷超時(shí)的網(wǎng)絡(luò)請(qǐng)求),避免資源泄露。
  • 可通過(guò)CancellationTokenSource創(chuàng)建令牌,支持設(shè)置超時(shí)(cts.CancelAfter(5000)),滿足工業(yè)場(chǎng)景的超時(shí)控制需求。
  1. 異步方法的異常處理
  • 異步方法中的異常會(huì)被封裝到Task中,只有在awaitTask時(shí),異常才會(huì)被拋出。
  • 推薦使用try-catch包裹await表達(dá)式,捕獲并處理特定異常(如網(wǎng)絡(luò)異常、IO 異常)。
try
{
    await tcpClient.ConnectAsync("127.0.0.1", 8888);
}
catch (SocketException ex)
{
    // 針對(duì)性處理Socket異常
    Console.WriteLine($"網(wǎng)絡(luò)連接異常:{ex.ErrorCode} - {ex.Message}");
}
  1. 網(wǎng)絡(luò)異步通信的額外優(yōu)化
  • 配置NetworkStream的讀寫超時(shí)(_networkStream.ReadTimeout = 5000;),避免無(wú)限等待。
  • 采用 “固定頭 + 數(shù)據(jù)體” 協(xié)議解決粘包 / 拆包問(wèn)題(工業(yè)級(jí)場(chǎng)景必備),異步接收時(shí)分段讀取,確保數(shù)據(jù)完整性。
  • 避免在ReceiveDataLoopAsync等異步循環(huán)中執(zhí)行耗時(shí)操作,可將數(shù)據(jù)放入消息隊(duì)列,由專門的線程處理業(yè)務(wù)邏輯。

四、總結(jié)

  1. C# 異步通信的核心是async/await模式,底層依賴Task類型,核心價(jià)值是非阻塞、高并發(fā)。
  2. 網(wǎng)絡(luò)異步通信優(yōu)先使用.NET 內(nèi)置的異步 API(如ConnectAsync、WriteAsync、ReadAsync),無(wú)需手動(dòng)管理線程。
  3. 實(shí)現(xiàn)關(guān)鍵:異步方法命名規(guī)范(后綴Async)、避免同步等待、合理使用CancellationToken、完善異常處理。
  4. 工業(yè)級(jí)場(chǎng)景中,異步通信需結(jié)合斷線重連、粘包處理、資源釋放等特性,確保穩(wěn)定性和可靠性。

以上就是在C#中實(shí)現(xiàn)異步通信的方法步驟的詳細(xì)內(nèi)容,更多關(guān)于C#實(shí)現(xiàn)異步通信的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C# 串口接收數(shù)據(jù)中serialPort.close()死鎖的實(shí)例

    C# 串口接收數(shù)據(jù)中serialPort.close()死鎖的實(shí)例

    下面小編就為大家分享一篇C# 串口接收數(shù)據(jù)中serialPort.close()死鎖的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2017-11-11
  • C#自定義字符串壓縮和解壓縮的方法

    C#自定義字符串壓縮和解壓縮的方法

    這篇文章主要介紹了C#自定義字符串壓縮和解壓縮的方法,通過(guò)自定義C#字符串操作類實(shí)現(xiàn)對(duì)字符串的壓縮與解壓的功能,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-04-04
  • C#借助Spire.XLS for .NET實(shí)現(xiàn)Excel工作表自動(dòng)化樣式設(shè)置

    C#借助Spire.XLS for .NET實(shí)現(xiàn)Excel工作表自動(dòng)化樣式設(shè)置

    作為C#開(kāi)發(fā)者,我們經(jīng)常需要處理Excel文件,本文將深入探討如何利用C#代碼,借助強(qiáng)大的Spire.XLS for .NET庫(kù),實(shí)現(xiàn)對(duì)整個(gè)Excel工作表的自動(dòng)化樣式設(shè)置,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-11-11
  • .Net筆記:System.IO之Stream的使用詳解

    .Net筆記:System.IO之Stream的使用詳解

    本篇文章是對(duì).Net中System.IO之Stream的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C#使用瀏覽按鈕獲得文件路徑和文件夾路徑的方法

    C#使用瀏覽按鈕獲得文件路徑和文件夾路徑的方法

    這篇文章主要介紹了C#使用瀏覽按鈕獲得文件路徑和文件夾路徑的方法,結(jié)合實(shí)例形式分析了C#瀏覽器事件響應(yīng)及文件操作相關(guān)技巧,需要的朋友可以參考下
    2017-05-05
  • C#實(shí)現(xiàn)中文驗(yàn)證碼的示例代碼

    C#實(shí)現(xiàn)中文驗(yàn)證碼的示例代碼

    這篇文章主要為大家詳細(xì)介紹了如何利用C#實(shí)現(xiàn)中文驗(yàn)證碼功能,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以了解一下
    2022-12-12
  • C#泛型的使用及示例詳解

    C#泛型的使用及示例詳解

    這篇文章主要介紹了C#泛型的使用及示例,本文通過(guò)例子個(gè)大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • 采用C#代碼動(dòng)態(tài)設(shè)置文件權(quán)限

    采用C#代碼動(dòng)態(tài)設(shè)置文件權(quán)限

    在開(kāi)發(fā)中,我們經(jīng)常會(huì)使用IO操作,例如創(chuàng)建,刪除文件等操作。在項(xiàng)目中這樣的需求也較多,我們也會(huì)經(jīng)常對(duì)這些操作進(jìn)行編碼,但是對(duì)文件的權(quán)限進(jìn)行設(shè)置,這樣的操作可能會(huì)手動(dòng)操作,本文介紹一種采用代碼動(dòng)態(tài)對(duì)文件設(shè)置權(quán)限的操作。
    2016-12-12
  • 在C# 8中如何使用默認(rèn)接口方法詳解

    在C# 8中如何使用默認(rèn)接口方法詳解

    這篇文章主要給大家介紹了關(guān)于在C# 8中如何使用默認(rèn)接口方法的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • C#開(kāi)發(fā)之Socket網(wǎng)絡(luò)編程TCP/IP層次模型、端口及報(bào)文等探討

    C#開(kāi)發(fā)之Socket網(wǎng)絡(luò)編程TCP/IP層次模型、端口及報(bào)文等探討

    我們?cè)谥v解Socket編程前,先看幾個(gè)和Socket編程緊密相關(guān)的概念
    2013-03-03

最新評(píng)論

礼泉县| 苏尼特右旗| 逊克县| 永平县| 图木舒克市| 白玉县| 扬中市| 兴义市| 佛山市| 凯里市| 农安县| 湟中县| 普安县| 绥化市| 岑巩县| 读书| 泗水县| 衢州市| 海口市| 满洲里市| 新巴尔虎右旗| 宜阳县| 龙陵县| 广灵县| 梓潼县| 文成县| 常德市| 班戈县| 潜山县| 南城县| 保山市| 平利县| 朝阳县| 罗山县| 枣庄市| 鄄城县| 綦江县| 新竹县| 宜兰县| 喀喇| 新巴尔虎左旗|