异常未被捕获 - 未处理的AggregateException [英] Exception is not caught - AggregateException unhandled

查看:244
本文介绍了异常未被捕获 - 未处理的AggregateException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人知道为什么下面的代码没有抓住我的ConnectionException,我花了几个小时...

  public async任务LoadContacts(string filter)
{
//我们将发送查询联系人消息给所有支持通讯录的服务器。
var addressBookServers = _addressBookService.GetAddressBookServerList();
//在这里创建任务数组,以便能够并行运行每个任务。
var tasksToProcess = new List< Task< SearchContactsResultDto>(addressBookServers.Count); (int i = 0; i< addressBookServers.Count; i ++)
tasksToProcess.Add(_addressBookService.SearchContactsAsync(addressBookServers [i] .Id,filterUpCaseNoDiacritics));



while(tasksToProcess.Count> 0)
{
var processedTask = await Task.WhenAny(tasksToProcess);
tasksToProcess.Remove(processedTask);
try
{
var serverResponse = await processedTask.ConfigureAwait(false);
var vmToAdd = serverResponse.SearchedContacts
.Where(sc =>!SearchedContacts.Exists(c => c.BabelName == sc.BabelName))
.Select(sc => ; CreateSearchContactViewModel(serverResponse.ServerId,null,sc.Name,sc.BabelName,sc.ContactId));

SearchedContacts.AddRange(vmToAdd);
}
catch(ErrorMessageException eme){Log.Warning(s => s.Set($An {nameof(ErrorMessageException)}类型为{eme.ErrorMessage.Cause},作为响应{nameof(Core.Json.Messages.MsgFindContacts)}。有关更多信息,请参阅异常详细信息。,eme)); }
catch(ConnectionException ce){Log.Info(s => s.Set($无法连接到服务器)类型{nameof(Core.Json.Messages.MsgFindContacts)}的消息无法发送,ce)); }
catch(TimeoutException te){Log.Info(s => s.Set($请求类型为{nameof(Core.Json.Messages.MsgFindContacts)}的消息)超时。细节,te)); }
catch(Exception){}
}
IsLoadingContacts = false;
}

当SearchContactsAsync引发异常时,此异常不会被LoadContacts方法捕获,作为未处理的AggregateException进行传播。
我已经写了一些单元测试,它们都通过,运行应用程序时出现问题。
我感谢任何帮助。



SearchContactsAsync实现:

  public async任务< SearchContactsResultDto> SearchContactsAsync(int serverId,string filter)
{
var msgFindContactsRes = await _communicationService.SendFindContactsAsync(serverId,filter)
.ConfigureAwait(false);

返回新的SearchContactsResultDto()
{
ServerId = serverId,
SearchedContacts = msgFindContactsRes.Contacts,
PageNumber = msgFindContactsRes.PageNumber,
PageSize = msgFindContactsRes.PageSize
};
}

SendFindContacsAsync impl:

  public Task< MsgFindContactsRes> SendFindContactsAsync(int serverId,string filter)
{
var serverSender = serverConnectionProvider.ProvideSender(serverId);

var msgFindContacts = messageFactory.CreateMsgFindContacts(filter);

返回serverSender.SendAsync< MsgFindContactsRes>(msgFindContacts);
}

SendAsync:

  public async任务< TExpectedResponse> SendAsync< TExpectedResponse>(IMessage消息)
其中TExpectedResponse:class,IMessage
{
if(message == null)
throw new ArgumentNullException($Argument {nameof }不能为空。);

var response = await _queue.ProvideAsync(message).ConfigureAwait(false);

if(response is TExpectedResponse)
返回响应为TExpectedResponse;
else throw new InvalidServerResponseException($对类型为{message.Header.Type}的消息的无效响应,预期消息类型:{typeof(TExpectedResponse).FullName},接收到的消息类型:{response.Header.Type} 。服务器ID:{_serverConnection.ServerId});
}

使用TPL队列和TCS提供同步:

  public Task< TItemResult> ProvideAsync(TItemData项目)
{
TaskCompletionSource< TItemResult> tcs = new TaskCompletionSource< TItemResult>();

// async入队其任务完成源的项目
_queue.SendAsync&QueueItem< TItemData,TItemResult>(新QueueItem< TItemData,TItemResult>(tcs,item));

return tcs.Task;
}

最后,使用TaskCompletionSource引发异常的队列消费者:

 私有async任务StartConsumer(Func< TItemData,TItemResult>消费者)
{
while(await _queue.OutputAvailableAsync())
{
QueueItem< TItemData,TItemResult> res = await _queue.ReceiveAsync();
try
{
var result = consumer(res.Data);
res.Tcs?.SetResult(result);
}
catch(异常e)
{
res?.Tcs.SetException(e);
throw;
}
}
}


解决方案

Do anyone know why the following code does not catch my ConnectionException, I've spend hours with it...

    public async Task LoadContacts(string filter)
    {
        // We will send find contacts message to all servers supporting addressbook.
        var addressBookServers = _addressBookService.GetAddressBookServerList();
        // Create task array here to be able to run each task in parallel manner.
        var tasksToProcess = new List<Task<SearchContactsResultDto>>(addressBookServers.Count);

        for (int i = 0; i < addressBookServers.Count; i++)
            tasksToProcess.Add(_addressBookService.SearchContactsAsync(addressBookServers[i].Id, filterUpCaseNoDiacritics));

        while (tasksToProcess.Count > 0)
        {
            var processedTask = await Task.WhenAny(tasksToProcess);
            tasksToProcess.Remove(processedTask);
            try
            {
                var serverResponse = await processedTask.ConfigureAwait(false);
                var vmToAdd = serverResponse.SearchedContacts
                .Where(sc => !SearchedContacts.Exists(c => c.BabelName == sc.BabelName))
                .Select(sc => CreateSearchContactViewModel(serverResponse.ServerId, null, sc.Name, sc.BabelName, sc.ContactId));

                SearchedContacts.AddRange(vmToAdd);
            }
            catch (ErrorMessageException eme) { Log.Warning(s => s.Set($"An {nameof(ErrorMessageException)} of type {eme.ErrorMessage.Cause} threw as a response to {nameof(Core.Json.Messages.MsgFindContacts)}. See exception details for further information.", eme)); }
            catch (ConnectionException ce) { Log.Info(s => s.Set($"Connection with server cannot be reached. Message of type {nameof(Core.Json.Messages.MsgFindContacts)} cannot be send", ce)); }
            catch (TimeoutException te) { Log.Info(s => s.Set($"Request on a message of type {nameof(Core.Json.Messages.MsgFindContacts)} timeouted. See exception details for further details.", te)); }
            catch (Exception) {}
        }
        IsLoadingContacts = false;
    }

When SearchContactsAsync throws an Exception, this exception is not catched by LoadContacts method and is propagated as a unhandled AggregateException. I've wrote some unit tests and they all pass, the problem occurs in running application. I appreciate any help.

SearchContactsAsync implementation:

public async Task<SearchContactsResultDto> SearchContactsAsync(int serverId, string filter)
    {
        var msgFindContactsRes = await _communicationService.SendFindContactsAsync(serverId, filter)
            .ConfigureAwait(false);

        return new SearchContactsResultDto()
        {
            ServerId = serverId,
            SearchedContacts = msgFindContactsRes.Contacts,
            PageNumber = msgFindContactsRes.PageNumber,
            PageSize = msgFindContactsRes.PageSize
        };
    }

SendFindContacsAsync impl:

public Task<MsgFindContactsRes> SendFindContactsAsync(int serverId, string filter)
    {
        var serverSender = serverConnectionProvider.ProvideSender(serverId);

        var msgFindContacts = messageFactory.CreateMsgFindContacts(filter);

        return serverSender.SendAsync<MsgFindContactsRes>(msgFindContacts);
    }

SendAsync:

public async Task<TExpectedResponse> SendAsync<TExpectedResponse>(IMessage message)
        where TExpectedResponse : class, IMessage
    {
        if (message == null)
            throw new ArgumentNullException($"Argument {nameof(message)} cannot be null.");

        var response = await _queue.ProvideAsync(message).ConfigureAwait(false);

        if (response is TExpectedResponse)
            return response as TExpectedResponse;
        else throw new InvalidServerResponseException($"Invalid response to a message of type {message.Header.Type}, expected message type: {typeof(TExpectedResponse).FullName}, received message type: {response.Header.Type}. Server id: {_serverConnection.ServerId}");
    }

ProvideAsync using TPL queue and TCS:

public Task<TItemResult> ProvideAsync(TItemData item)
    {
        TaskCompletionSource<TItemResult> tcs = new TaskCompletionSource<TItemResult>();

        // async enqueue an item with its task completion source
        _queue.SendAsync<QueueItem<TItemData, TItemResult>>(new QueueItem<TItemData, TItemResult>(tcs, item));

        return tcs.Task;
    }

And finally the queue consumer which throws an exception using the TaskCompletionSource:

private async Task StartConsumer(Func<TItemData, TItemResult> consumer)
    {
        while (await _queue.OutputAvailableAsync())
        {
            QueueItem<TItemData, TItemResult> res = await _queue.ReceiveAsync();
            try
            {
                var result = consumer(res.Data);
                res.Tcs?.SetResult(result);
            }
            catch (Exception e)
            {
                res?.Tcs.SetException(e);
                throw;
            }
        }
    }

解决方案

Oh well, I can see the problem right now. The last line of the code I've posted... it throws the exception again which is never ever caught... What a bad mistake. Anyway, thanks all participates for help...

这篇关于异常未被捕获 - 未处理的AggregateException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆