首页 > 解决方案 > 等待带有循环的任务也等待

问题描述

首先感谢您的阅读。我在这里是因为在我的一个项目中,我在一个循环中连续接收数据包,但是当我关闭我的应用程序时,我从我在 ReceiveLoop 中调用的 ReceivePackets 方法获得了一个 ObjectDisposedException,所以我很喜欢,我只是必须等到 _receiveTask 完成才能关闭我的流和 tcp 客户端,但我的 _receiveTask 返回完成,甚至没有到达方法的末尾。

我尝试使用 Thread 但同样的问题

开始任务

if (_receiveTask == null)
{
    _receiveTask = Task.Run(new Action(ReceiveLoop));
}

在任务中循环

private async void ReceiveLoop()
{
    while (_client.Connected && _run)
    {
        await ReceivePackets();
    }
}

接收数据包任务

private async Task<List<Packet>> ReceivePackets()
{
    var bytes = new byte[_client.ReceiveBufferSize];
    int size = await _stream.ReadAsync(bytes, 0, bytes.Length);
    List<Packet> packets = Decrypt(bytes, size).Select(p => new Packet(p)).ToList();
    foreach (var packet in packets)
    {
        Dispatch(() => PacketReceived?.Invoke(packet));
    }
    return packets;
}

使用的停止方法

public async Task Stop()
{
    if (_client.Connected)
    {
        _run = false;
        await _receiveTask;
        _stream.Close();
        _client.Close();
    }
}

在 Stop 方法中,_receiveTask 被视为已完成,但是当我在 ReceiveLoop 中的 while 循环之后打印一些内容时,它甚至没有被打印出来。

标签: c#async-await

解决方案


那是因为ReceiveLoop实际上在其所有代码完成之前“返回”,就像大多数async方法一样。您需要让它返回 aTask然后等待它,而不是Task基于该操作创建一个新的。

private async Task ReceiveLoop()
{
    while (_client.Connected && _run)
    {
        await ReceivePackets();
    }
}

...

_receiveTask = ReceiveLoop();

推荐阅读