C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > C#实现异步通信

在C#中实现异步通信的方法步骤

作者:工业程序猿老赵

C# 的异步通信基于 async/await 模式,其底层依赖Task和Task<TResult>类型来封装异步操作,本文给大家介绍了在C#中实现异步通信的方法步骤,需要的朋友可以参考下

一、C# 异步通信的核心基础

C# 的异步通信基于 async/await 模式(这是.NET 4.5 及以上版本推荐的异步编程模型,简化了传统的回调地狱问题),其底层依赖TaskTask<TResult>类型来封装异步操作,核心目标是避免阻塞调用线程(尤其是 UI 线程、主线程),提升程序的并发处理能力和响应性

1. 核心关键字与类型

2. 最简单的异步方法示例(同步方法改造为异步)

// 同步方法
public string GetSyncData()
{
    // 模拟耗时操作(如文件读取、网络请求)
    Thread.Sleep(2000);
    return "同步数据";
}

// 异步方法(改造后)
public async Task<string> GetAsyncData()
{
    // 用Task.Delay替代Thread.Sleep(异步等待,不阻塞线程)
    await Task.Delay(2000);
    return "异步数据";
}

// 调用异步方法
public async Task CallAsyncMethod()
{
    Console.WriteLine("开始调用异步方法");
    string result = await GetAsyncData(); // 等待异步操作完成,不阻塞当前线程
    Console.WriteLine($"异步方法返回结果:{result}");
}

二、C# 网络异步通信(TCP 为例)的核心实现

网络通信是异步通信的典型场景(TCP/UDP/HTTP 等),.NET 提供了丰富的异步 API(后缀为Async,无需手动创建线程,即可实现高效的异步网络通信,核心依赖TcpClientNetworkStream的异步方法。

核心异步 API(对应工业级 TCP 客户端场景)

  1. TcpClient.ConnectAsync():异步连接 TCP 服务端,替代同步的Connect()
  2. NetworkStream.WriteAsync():异步向网络流写入数据(发送数据),替代同步的Write()
  3. NetworkStream.ReadAsync():异步从网络流读取数据(接收数据),替代同步的Read()
  4. 上述方法均支持传入CancellationToken,用于取消异步操作(优雅终止任务)。

完整实战:TCP 异步通信(客户端)

基于async/await实现 TCP 客户端的异步发送和接收,延续工业级场景的可靠性设计:

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; // 用于取消异步接收循环

        // 连接状态
        public bool IsConnected => _tcpClient?.Connected == true && _networkStream != null;

        /// <summary>
        /// 异步连接服务端
        /// </summary>
        public async Task<bool> ConnectAsync(string serverIp, int serverPort)
        {
            try
            {
                _cts = new CancellationTokenSource();
                _tcpClient = new TcpClient();

                // 异步连接:不阻塞当前线程,等待连接完成
                await _tcpClient.ConnectAsync(serverIp, serverPort);
                _networkStream = _tcpClient.GetStream();

                Console.WriteLine("成功连接到服务端");
                // 启动异步接收循环(后台持续监听数据,不阻塞主线程)
                _ = ReceiveDataLoopAsync(_cts.Token);

                return true;
            }
            catch (SocketException ex)
            {
                Console.WriteLine($"连接失败:{ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 异步发送数据
        /// </summary>
        public async Task<bool> SendDataAsync(string message)
        {
            if (!IsConnected || string.IsNullOrEmpty(message))
                return false;

            try
            {
                byte[] sendData = Encoding.UTF8.GetBytes(message);
                // 异步写入网络流:不阻塞当前线程,等待数据发送完成
                await _networkStream!.WriteAsync(sendData, 0, sendData.Length);
                await _networkStream.FlushAsync(); // 异步刷新缓冲区

                Console.WriteLine($"成功发送数据:{message}");
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"发送数据失败:{ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 异步接收数据循环(持续监听服务端数据)
        /// </summary>
        private async Task ReceiveDataLoopAsync(CancellationToken cancellationToken)
        {
            if (!IsConnected)
                return;

            byte[] buffer = new byte[1024]; // 接收缓冲区
            try
            {
                while (!cancellationToken.IsCancellationRequested && IsConnected)
                {
                    // 异步读取网络流:无数据时挂起,不阻塞线程,有数据时恢复执行
                    int receivedBytes = await _networkStream!.ReadAsync(buffer, 0, buffer.Length, cancellationToken);

                    if (receivedBytes == 0)
                    {
                        Console.WriteLine("服务端主动关闭连接");
                        break;
                    }

                    // 解析接收到的数据
                    string receivedMessage = Encoding.UTF8.GetString(buffer, 0, receivedBytes);
                    Console.WriteLine($"接收到服务端数据:{receivedMessage}");
                }
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("接收循环已被取消");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"接收数据异常:{ex.Message}");
            }
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            _cts?.Cancel(); // 取消异步接收循环
            _networkStream?.Dispose();
            _tcpClient?.Dispose();
            Console.WriteLine("已断开连接并释放资源");
        }
    }

    // 调用示例
    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;

            // 循环异步发送数据
            int sendCount = 0;
            while (tcpClient.IsConnected)
            {
                sendCount++;
                string message = $"异步通信测试 {sendCount} - {DateTime.Now:HH:mm:ss}";
                await tcpClient.SendDataAsync(message);

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

三、异步通信的关键特性与注意事项

  1. await的非阻塞特性
  1. 避免 “异步同步化”(常见坑)
  1. CancellationToken的使用
  1. 异步方法的异常处理
try
{
    await tcpClient.ConnectAsync("127.0.0.1", 8888);
}
catch (SocketException ex)
{
    // 针对性处理Socket异常
    Console.WriteLine($"网络连接异常:{ex.ErrorCode} - {ex.Message}");
}
  1. 网络异步通信的额外优化

四、总结

  1. C# 异步通信的核心是async/await模式,底层依赖Task类型,核心价值是非阻塞、高并发
  2. 网络异步通信优先使用.NET 内置的异步 API(如ConnectAsyncWriteAsyncReadAsync),无需手动管理线程。
  3. 实现关键:异步方法命名规范(后缀Async)、避免同步等待、合理使用CancellationToken、完善异常处理。
  4. 工业级场景中,异步通信需结合断线重连、粘包处理、资源释放等特性,确保稳定性和可靠性。

以上就是在C#中实现异步通信的方法步骤的详细内容,更多关于C#实现异步通信的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文