用循环等待任务

时间:2019-06-10 14:46:57

标签: c# async-await

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

我尝试使用线程代替,但存在相同的问题

开始任务

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循环之后放置一些内容时,甚至没有进行打印。

1 个答案:

答案 0 :(得分:4)

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

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

...

_receiveTask = ReceiveLoop();