Обработка исключения согласования в SignalR

У меня есть приложение Silverlight 5, обращающееся к серверу с помощью SignalR. В большинстве случаев это работает нормально, но время от времени при запуске в режиме отладки я получаю сообщение об ошибке во время согласования. Я думаю, что это может быть из-за того, что в моей локальной установке ISS заканчиваются соединения.

В любом случае, когда это происходит, вызывается обработчик необработанных исключений в моем приложении. Я хочу изменить это, чтобы я мог обрабатывать исключение, локальное для инициализации SignalR. Я не хочу, чтобы ошибка согласования распространялась на мой центральный обработчик ошибок.

У меня есть кусок кода, который выглядит следующим образом:

     var uri = Application.Current.Host.Source.GetComponents(UriComponents.Scheme | UriComponents.HostAndPort, UriFormat.Unescaped);

     _hubConnection = new HubConnection(uri);
     var hub = _hubConnection.CreateProxy("stuffhub");
     hub.On<Stuff>("Stuff", message => DoStuff());

     var transport = new LongPollingTransport();
     _hubConnection.Start(transport);

Этот код в большинстве случаев выполняется нормально, но иногда следующее исключение передается моему центральному обработчику необработанных исключений через несколько секунд после выполнения приведенного выше кода.

Message: Exception(s) occurred : .
[ Exception(s) occurred : .
[ Exception(s) occurred : .
[ Exception(s) occurred : .
[ System.InvalidOperationException: Server negotiation failed.
   vid SignalR.Client.Transports.HttpBasedTransport.<GetNegotiationResponse>b__0(IResponse     response)
   vid SignalR.TaskAsyncHelper.FromMethod[T1,TResult](Func`2 func, T1 arg) ]
 ]
 ]

]

StackTrace ApplicationUnhandledExceptionEventArgs:

 at System.Threading.Tasks.Task.Finalize()

person Nitramk    schedule 10.09.2012    source источник
comment
У меня нет опыта работы с C#, но нет ли чего-то подобного, например, try{} catch{} ?   -  person xorinzor    schedule 13.09.2012
comment
SignalR запускает асинхронные задачи в C#. Они работают в фоновом потоке, поэтому попытка/улов не сработает. Обычно можно дождаться завершения задачи и проверить, не возникло ли исключение. Проблема здесь в том, что первые асинхронные задачи порождают новую дочернюю асинхронную задачу, а затем завершаются. Первая задача завершается нормально, но ее дочерняя задача завершается со сбоем. И я не могу понять, как справиться с результатом сбоя дочерней задачи.   -  person Nitramk    schedule 13.09.2012
comment
возможно, пусть родитель подождет, пока ребенок не вернет обратный вызов? в этом случае вы сможете использовать try/catch   -  person xorinzor    schedule 13.09.2012


Ответы (2)


Как сказал Джон Скит, вам нужно обработать исключение из задачи, возвращенной из Start().

var uri = Application.Current.Host.Source.GetComponents(UriComponents.Scheme | UriComponents.HostAndPort, UriFormat.Unescaped);

 _hubConnection = new HubConnection(uri);
 var hub = _hubConnection.CreateProxy("stuffhub");
 hub.On<Stuff>("Stuff", message => DoStuff());

 _hubConnection.Start().ContinueWith(task => 
 {
     if(task.IsFaulted) {
         Debug.WriteLine("Error starting -" + task.Exception.GetBaseException());
     }
 });
person davidfowl    schedule 14.09.2012
comment
Хороший. Я не осознавал, что мне нужно было фактически наблюдать за исключением, вызывая task.Exception, чтобы исключение не распространялось на мой необработанный обработчик исключений. Я играл с кодом task.IsFaulted, но на самом деле я никогда не обращался к исключению таким образом. Интересно, действительно ли просмотр исключения с помощью окна просмотра отладчика предотвращает повторное создание исключения. Объяснил бы мое замешательство при попытке отладить это. Наслаждайтесь своими 300 баллами. - person Nitramk; 14.09.2012
comment
Теперь вы поняли. StackOverflow не позволил мне немедленно назначить награду после того, как ваш ответ был установлен как правильный. По какой-то причине сначала мне пришлось ждать около 3 часов. Что совпало с моей регистрацией и уходом из офиса. ;-) - person Nitramk; 16.09.2012

Мне не ясно, какая именно задача выдает исключение, но если она находится под вашим контролем, вы можете просто добавить продолжение:

task.ContinueWith(t => {
    // Depending on t.Status (cancelled or faulted) you could perform logging
    // or whatever... presumably nothing's watching for the task to complete,
    // otherwise *it* would see the exception...
}, TaskContinuationOptions.NotOnRanToCompletion);

Конечно, если вы можете использовать .NET 4.5 и C# 5, async/await может вам помочь — это зависит от того, что делает SignalR.

person Jon Skeet    schedule 13.09.2012
comment
Правильно, вы Start() возвращаете задачу, поэтому вы можете сделать Start().ContinueWith(..) - person davidfowl; 14.09.2012