C# 保证异步方法顺序执行

通常会有一些异步方法需要顺序执行,如对一个Socket进行异步发送,想要确保信息按照调用异步时的顺序进行发送,但使用普通的异步方法不能保证发送顺序,会导致对方接受结果为乱序发送。

具体实现思路:首先为每一个顺序声明一个ValueTask或Task全局变量a,然后每次调用异步方法时等待a中存储的前一个ValueTask或Task,同时将此次异步方法返回给a,这样就能实现异步的顺序发送。具体代码如下:

接收端代码:

{
    Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    socket.Bind(IPEndPoint.Parse("127.0.0.1:8888"));
    byte[] buffer = new byte[10240];
    socket.Listen(1);
    Socket client = socket.Accept();
    Thread.Sleep(5000);
    client.Receive(buffer);
    Console.WriteLine(Encoding.UTF8.GetString(buffer));
}

发送端代码(不进行异步顺序处理):

{
    Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    socket.Connect(IPEndPoint.Parse("127.0.0.1:8888"));
    {
    	for (int i = 0; i < 100; i++)
        {
        	Send_(socket, Encoding.UTF8.GetBytes($"{i}\n"));
        }
    }
}

static async void Send_(Socket socket,ReadOnlyMemory<byte>msgMem)
{
    await Task.Delay(random.Next(10, 50));    //模拟多个方法处理时间不同操作
    socket.SendAsync(msgMem);
}

普通异步方法输出:在这里插入图片描述

发送端代码(顺序异步):

{
    Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    socket.Connect(IPEndPoint.Parse("127.0.0.1:8888"));
    {
        for (int i = 0; i < 100; i++)
        {
            globalVT = SendNext(socket, Encoding.UTF8.GetBytes($"{i}\n"));
        }
    }
}
static ValueTask<int> globalVT = default;
static async ValueTask<int> SendNext(Socket socket, ReadOnlyMemory<byte> msgMem)
{
    //在一个代码块中,阻塞等待和赋值给globalVT二者不能同时发生,曲线救国
    await globalVT;
    return await send(socket, msgMem);
}
static async ValueTask<int> send(Socket socket, ReadOnlyMemory<byte> msgMem)
{
    //异步方法,模拟延时操作
    await Task.Delay(random.Next(10, 50));
    return await socket.SendAsync(msgMem);
}  

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C# 中,可以使用 `Task` 类来创建异步任务。具体实现方式如下: 1. 声明一个异步方法,例如 `DoAsyncTask`,并在方法体中编写你要执行的异步操作。注意,异步方法的返回类型应该是 `Task` 或 `Task<T>`。 ```csharp async Task DoAsyncTask() { // 异步操作代码 } ``` 2. 调用异步方法时,使用 `await` 关键字等待异步方法执行完毕。 ```csharp await DoAsyncTask(); ``` 3. 在异步方法中,可以使用 `Task.Run` 方法来以异步方式执行一个方法。 ```csharp async Task DoAsyncTask() { await Task.Run(() => { // 要异步执行方法 }); } ``` 完整的代码示例如下: ```csharp using System; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { Console.WriteLine("Before async task"); await DoAsyncTask(); Console.WriteLine("After async task"); } static async Task DoAsyncTask() { await Task.Run(() => { Console.WriteLine("Async task started"); // 模拟异步操作 Task.Delay(1000).Wait(); Console.WriteLine("Async task finished"); }); } } ``` 在这个示例中,`Main` 方法中先输出 "Before async task",然后调用异步方法 `DoAsyncTask`,等待异步方法执行完毕后输出 "After async task"。在 `DoAsyncTask` 方法中,使用 `Task.Run` 方法来异步执行一段代码,其中包含了一个 1 秒钟的延迟操作。运行这个程序,你会发现输出的顺序是: ``` Before async task Async task started Async task finished After async task ``` 这说明异步任务已经成功执行

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值