Предотвратить исключения из обратных вызовов WCF - PullRequest
2 голосов
/ 25 февраля 2010

Я делаю небольшое приложение для чата. Я дошел до того, что один клиент отправляет сообщение, а затем, используя обратные вызовы других клиентов в комнате, они быстро получают сообщение. Таким образом, если в комнате 10 человек, экземпляр службы клиента, отправляющего сообщение, вызовет это в 10 потоках:

targetCallback.RecieveMessage(message);

Теперь интернет-соединения нестабильны, и может случиться так, что они прервутся за мгновение до того, как это будет выполнено, поэтому будет сгенерировано исключение, и экземпляр клиента будет автоматически уничтожен, оставив сообщение неотправленным или наполовину успешным.

Я нашел примеры, которые вообще не обрабатывают эти исключения, в то время как другие описывают простое:

try
{
    targetCallback.RecieveMessage(message);
}
catch
{
}

Но разве это лучший способ обработать это исключение?

Ответы [ 2 ]

3 голосов
/ 25 февраля 2010

См

http://msdn.microsoft.com/en-us/library/aa354510.aspx

за добрый совет. Вкратце, вы должны поймать TimeoutException и CommunicationException.

2 голосов
/ 25 февраля 2010

Я также видел ObjectDisposedExceptions при вызове обратных вызовов WCF и, возможно, какой-то SecurityException, но я не могу вспомнить, какой именно.

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

Обычно я также собираю некоторую контекстную информацию о соединении из OperationContext, такую ​​как IP-адрес, sessionID и токен пользователя, чтобы я мог определить, кто не прошел, и зарегистрировать его. Но это оставлено читателю в качестве упражнения.

public interface ICallbackContract
{
    void Operation(string arg);
}

class Program
{
    private List<ICallbackContract> Callbacks;

    private void SendMessage(string msg)
    {
        lock (this.Callbacks)
        {
            foreach (var callback in this.Callbacks)
            {
                this.InvokeWcf(callback, (c) => c.Operation(msg));
            }
        }
    }

    public void InvokeWcf(this ICallbackContract contract, Action<ICallbackContract> op)
    {
        if (((ICommunicationObject)contract).State != CommunicationState.Opened)
        {
            lock (this.Callbacks)
                Callbacks.Remove(contract);
            myLogger.LogError("That contract isn't open! Disconnected.");
            return;
        }

        try
        {
            op(contract);
        }
        catch (TimeoutException ex)
        {
            lock (this.Callbacks)
                Callbacks.Remove(contract);
            myLogger.LogError("That contract timed out! Disconnected.", ex);
            return;
        }
        catch (CommunicationException ex)
        {
            ...
        }
        catch (ObjectDisposedException ex)
        {
            ...
        }
        catch (Exception ex)
        }
            // Unexpected case.
            lock (this.Callbacks)
                Callbacks.Remove(contract);
            myLogger.FatalError("Something really bad happened!.", ex);
            throw;
        {
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...