等待方法返回空集合,除非我在里面使用断点

时间:2016-04-10 17:19:32

标签: c# asynchronous async-await

我正在用C#编写一个程序,它将从其他程序中读取消息,它需要读取消息,并在某些情况下准备和发送响应。 我编写了这个方法来处理单个消息,我将其异步调用(使用await)或同步调用它,具体取决于其类型。

public async void HandleMessage(Message message)
{
    IEnumerable<Tuple<Message, ulong>> responses;
    try
    {
        if (!_communicateTypesToHandleSync.Contains(message.GetType()))
        {
             responses = await Task.Run(() => _requestHandler.HandleRequest(message));
        }
        else
        {
            responses = _requestHandler.HandleRequest(message);
        }
        foreach (var response in responses)
        {
            CSMessageHandler.AddMessageToSend(response.Item1, response.Item2);
        }
    }
    catch (Exception ex)
    {
        _logger.Error(ex, "Error while handling message");
    }
}

问题是使用await调用HandleRequest似乎总是返回一个空集合(我用条件断点检查它)。 我试图调试它,当我终于发现发生了什么时,我在HandleRequest的末尾设置了一个断点,只有当集合不为空时才会停止。在此断点处,代码执行已停止,当我从HandleRequest退出时,即使在HandleMessage我也没有空responses

1 个答案:

答案 0 :(得分:2)

如果无效,则HandleMessage应返回 Task Task<IEnumerable<Tuple<Message, ulong>>> 如果您想返回IEnumerable<Tuple<Message, ulong>>。除非是代表,否则不应使用void。

您的代码应为

public async Task<IEnumerable<Tuple<Message, ulong>>> HandleMessage(Message message)
{
    IEnumerable<Tuple<Message, ulong>> responses;
    try
    {
        if (!_communicateTypesToHandleSync.Contains(message.GetType()))
        {
             responses = await Task.Run(() => _requestHandler.HandleRequest(message));
        }
        else
        {
            responses = _requestHandler.HandleRequest(message);
        }
        foreach (var response in responses)
        {
            CSMessageHandler.AddMessageToSend(response.Item1, response.Item2);
        }

        return responses;
    }
    catch (Exception ex)
    {
        _logger.Error(ex, "Error while handling message");
    }
}

你的电话应该是

await HandleMessage(Message message);

由于该方法无效,因此当您调用 HandleMessage 时,无法等待。该方法在1个线程上输入,然后执行 Task.Run 以启动另一个线程。当第二个线程启动时,线程1被释放并继续在调用函数上运行。

例如:

//do one thing
HandleMessage(message);
//Do other work

Task.Run 旋转另一个线程时,线程1将在释放时继续执行其他工作。