Лучший способ поймать исключение WCF в Silverlight?
У меня есть приложение Silverlight 2, которое использует службу WCF. Таким образом, он использует асинхронные обратные вызовы для всех вызовов методов службы. Если служба не запущена или сбой, или сеть опускается, и т.д. До или во время одного из этих вызовов, генерируется исключение, как и следовало ожидать. Проблема в том, что я не знаю, как поймать это исключение.
-
Поскольку это асинхронный вызов, я не могу завершить мой начальный вызов блоком try/catch и получить его исключение, которое происходит после того, как программа переместилась с этой точки.
-
Поскольку прокси-сервер службы автоматически генерируется, я не могу поместить блок try/catch для каждой генерируемой функции, которая вызывает EndInvoke (где действительно появляется исключение). Эти сгенерированные функции также окружены внешним кодом в стеке вызовов, поэтому нигде в стеке не нужно ставить try/catch.
-
Я не могу поместить try/catch в мои функции обратного вызова, потому что это исключение происходит до того, как они будут вызваны.
-
В моем приложении App.xaml.cs есть функция Application_UnhandledException, которая фиксирует все необработанные исключения. Я мог бы использовать это, но это похоже на грязный способ сделать это. Я бы предпочел зарезервировать эту функцию для поистине неожиданных ошибок (ака ошибок) и не в конечном итоге с кодом в этой функции для каждого обстоятельства, с которым я хотел бы заниматься определенным образом.
Я пропустил очевидное решение? Или я придерживаюсь с помощью Application_UnhandledException?
[Изменить]
Как уже упоминалось ниже, свойство Error - это именно то, что я искал. То, что бросает меня за цикл, состоит в том, что тот факт, что исключение выбрано и кажется неотображенным, но исполнение может продолжаться. Он запускает событие Application_UnhandledException и заставляет VS2008 прерывать выполнение, но продолжение в отладчике позволяет продолжить выполнение. Это не проблема, это кажется странным.
Ответы
Ответ 1
Я проверяю свойство Error для аргументов события в обработчике обработанных методов службы. У меня не было проблем с вызовом обработчика события. В случае, когда сервер идет вниз, вызов занимает несколько секунд, а затем возвращается с исключением ProtocolException в свойстве Error.
Предполагая, что вы пробовали это, и ваш callback действительно никогда не вызывается, вы можете изучить настройку сгенерированного класса прокси. См. в этой статье.
Ответ 2
Я нашел тему форума, которая говорила об этом, и в нем упоминается, что наилучшей практикой является использование свойства Error. Между этой нитью и моими собственными переживаниями я могу заключить:
-
В обычном коде .NET сгенерированный класс прокси обрабатывает исключение должным образом, помещая исключение в свойство Error, а не бросая его.
-
В Silverlight созданный класс прокси устанавливает свойство Error, но не полностью обрабатывает исключение. Исключение выбирается отладчиком, который выдает окно исключения с сообщением "Исключение ProtocolException было не обработано кодом пользователя". Несмотря на это сообщение, исключение не похоже на функцию Application_UnhandledException.
Я бы ожидал, что это одна из вещей, которые они исправят в финальной версии.
В настоящее время я буду использовать свойство Error и просто обработать отладчик, нарушающий выполнение. Если это становится слишком раздражающим, я могу отключить исключение для исключения для протоколаException.
Ответ 3
Вы можете забыть о Application_UnhandledException для обратных вызовов клиента asyn, почему:
Application_UnhandledException только исключения, запущенные в потоке пользовательского интерфейса, могут быть захвачены Application.UnhandledExceptions
Это означает, что... не вызывался вообще для асинхронного вызова WCF: -).
Проверить подробный ответ от MSFT
http://silverlight.net/forums/t/21828.aspx
Здравствуйте, только исключения, запущенные в потоке пользовательского интерфейса, могут быть захвачены Application.UnhandledExceptions. Он не может перехватывать исключения из других потоков. Вы можете попробовать это, чтобы устранить проблему: в Visual Studio из меню Debug выберите "Исключения". Затем установите флажок "Исключения общего времени выполнения языка". Это заставит отладчик останавливаться всякий раз, когда генерируется исключение. Но обратите внимание, что это может быть довольно неприятно, потому что даже если исключение уже поймано. Вы можете использовать CheckBoxes для фильтрации исключений, которые вы хотите поймать.
Хорошая новость в моем случае заключается в том, что обработка сообщения об ошибке только в обратном вызове службы clietn достаточно, если вы не отлаживаете.
Спасибо
Braulio
Ответ 4
OOpps....
Извините неправильный ответ с моей стороны (ну, парень MSFT не попал в ответ на вызов службы ответа, вызываемые вызовы в одном и том же потоке пользовательского интерфейса), вещь
Дополнительная информация:
- In development even detaching from the debugger, this method is never reached.
- On the production environment yes.
Мое предположение связано с параметрами Visual Studio и перехватами исключений.
Дополнительная информация, в этой теме
http://silverlight.net/forums/p/48613/186745.aspx#186745
Довольно интересная тема.
Ответ 5
Я не сантехник, поэтому решил создать свой собственный класс сервисов WCF, который переопределяет некоторые функциональные возможности файла класса "reference.cs", который автоматически генерируется Visual Studio, затем я добавил свой собственный try/блоки захвата для обнаружения ошибок связи.
Созданный мной класс выглядит примерно так:
public class myWCFService : MyWCFServiceClient
{
protected override MyController.MyService.IMyWCFService CreateChannel()
{
return new MyWCFServiceClientChannel(this);
}
}
private class MyWCFServiceClientChannel : ChannelBase<MyController.MyService.IMyWCFService>, MyController.MyService.IMyWCFService
{
/// <summary>
/// Channel Constructor
/// </summary>
/// <param name="client"></param>
public MyWCFServiceClientChannel(System.ServiceModel.ClientBase<MyController.MyService.IMyWCFService> client) :
base(client)
{
}
/// <summary>
/// Begin Call To RegisterUser
/// </summary>
/// <param name="memberInformation"></param>
/// <param name="callback"></param>
/// <param name="asyncState"></param>
/// <returns></returns>
public System.IAsyncResult BeginRegisterUser(MyDataEntities.MembershipInformation memberInformation, System.AsyncCallback callback, object asyncState)
{
object[] _args = new object[1];
_args[0] = memberInformation;
System.IAsyncResult _result = base.BeginInvoke("RegisterUser", _args, callback, asyncState);
return _result;
}
/// <summary>
/// Result from RegisterUser
/// </summary>
/// <param name="result"></param>
/// <returns></returns>
public MyDataEntities.MembershipInformation EndRegisterUser(System.IAsyncResult result)
{
try
{
object[] _args = new object[0];
MyDataEntities.MembershipInformation _result = ((MyDataEntities.MembershipInformation)(base.EndInvoke("RegisterUser", _args, result)));
return _result;
}
catch (Exception ex)
{
MyDataEntities.MembershipInformation _result = new MyDataEntities.MembershipInformation();
_result.ValidationInformation.HasErrors = true;
_result.ValidationInformation.Message = ex.Message;
return _result;
}
}
}
Ответ 6
С Silverlight 3 отладчик Visual Studio ловит эти исключения, так что обработчик исключений - смутно - никогда не достигается. Однако при запуске без отладчика обработчик исключений вызывается как ожидалось. Я думаю, это нормально, если вы это осознаете. Я признаю, что потратил несколько часов, пытаясь понять, как развернуть внутреннюю работу Silverlight/Wcf/Browser, чтобы добраться до моего исключения. Не ходите туда.
Ответ 7
Использование настраиваемого генератора прокси-сервера WCF является хорошим решением для обработки асинхронных исключений в Silverlight.Click здесь для загрузки исходного кода.
Ответ 8
С XNA на WP7 я обнаружил, что у меня не было выбора, кроме как вручную добавить try/catch в различные методы async End * FunctionName *(); ничто другое, что я пытался, предотвратит сбой приложения и завершение работы, когда сервер будет недоступен. Это реальное перетащить, чтобы вручную обновить этот код при изменении службы.
Я удивлен, что это не большая проблема, поскольку, похоже, нет никакого другого способа поймать эти исключения на WP7, используя XNA, но я полагаю, что это просто говорит о том, сколько людей (== не многие) пытаясь сделать это, чем что-либо еще. Если бы они просто сделали slsvcutil.exe генерировать методы синхронизации, мы могли бы легко поймать их внутри нашего собственного рабочего потока, но, к сожалению, сгенерированный код использует потоки пула потоков, не имея возможности поймать исключения.
Ответ 9
Чтобы справиться с этой ситуацией, используйте исключение TargetInvocationException. Это поймает исключение, если сеть не работает или ваша служба недоступна.