Как получить доступ к начальным параметрам в обратном вызове асинхронного запроса WCF? - PullRequest
1 голос
/ 29 августа 2011

В настоящее время я обновляю клиентское приложение, которое использует веб-службу WCF от синхронных до асинхронных вызовов. Основной сервер и клиент находятся в одной локальной сети, но приложение слишком ненадежно зависает, ожидая ответа.

Приложение использует 4 одинаковых конечных точки на 2 серверах (поэтому, если экземпляр вышел из строя или сервер находится в автономном режиме, все равно нужно что-то вызвать).

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

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

Каков наилучший способ передачи параметров из метода Begin в метод обратного вызова? Они хранятся где-нибудь в клиентском объекте? Это можно сделать с помощью мероприятия или хранить их на уровне класса?

    public delegate void GetUserInfoCompletedEventHandler(UserInfo e);
    public static event GetUserInfoCompletedEventHandler GetUserInfoCompleted;
    public delegate void GetUserInfoFaultedEventHandler(string errorMessage);
    public static event GetUserInfoFaultedEventHandler GetUserInfoFaulted;


        public static void BeginGetUserInfo(string fobID)
    {
        MyClient client = new MyClient(availableEndpoints[activeEndpointIndex].Name);
        client.GetUserInfoCompleted += new EventHandler<GetUserInfoCompletedEventArgs>(client_GetUserInfoCompleted);
        client.GetUserInfoAsync(fobID);
    }


static void client_GetUserInfoCompleted(object sender, GetUserInfoCompletedEventArgs e)
    {
        // Get the instance of the client
       MyClient client = (MyClient)sender;      

        if (null == e.Error)
        {
            // Close the client instance if there was no error
            try { client.Close(); }
            catch { }

            if ((null != GetUserInfoCompleted) && (null != e.Result))
            {
                // Report as successful and raise the event
                ServiceActionSuccessful();
                GetUserInfoCompleted(e.Result);
            }
        }
        else
        {
            // Abort the client as there was an error
            try { client.Abort(); }
            catch { }

            if (e.Error is FaultException<WebServiceError>)
            {
                FaultException<WebServiceError> fault = (FaultException<WebServiceError>)e.Error;

                if (null != GetUserInfoFaulted)
                {
                    // A fault occurred in the web service
                    GetUserInfoFaulted(fault.Detail.ErrorMessage);
                }
            }
            else
            {
                // Assume this was problem in connection so test if there any more endpoints to attempt
                bool isNextEndpointAvaialble = ServiceActionFailure();

                if (isNextEndpointAvaialble)
                {
                    // If there are more endpoints to try, call the method to run again
                    BeginGetUserInfo(); // Need parameters here
                }
                else
                {
                    if (null != GetUserInfoFaulted)
                    {
                        // No more endpoints to try
                        GetUserInfoFaulted(Errors.GetUserFriendlyMessage(e.Error));
                    }
                }
            }
        }
    }

1 Ответ

1 голос
/ 29 августа 2011

Если MyClient является сгенерированным классом, должна быть вторая функция с именем

MyClient.GetUserInfoAsync(string fobID, object userState);

. Содержимое аргумента userState передается непосредственно в свойство GetUserInfoCompletedEventArgs.UserState в аргументах события, полученныхclient_GetUserInfoCompleted.

Таким образом, вы можете сделать что-то вроде этого:

public static void BeginGetUserInfo(string fobID)
{
    MyClient client = new MyClient(availableEndpoints[activeEndpointIndex].Name);
    client.GetUserInfoCompleted += new EventHandler<GetUserInfoCompletedEventArgs>(client_GetUserInfoCompleted);
    client.GetUserInfoAsync(fobID, fobID);
}

static void client_GetUserInfoCompleted(object sender, GetUserInfoCompletedEventArgs e)
{
    string fobID = e.UserState as string;
    // handle the event here...
}

Другая альтернатива - использовать лямбду для обработки события:

public static void BeginGetUserInfo(string fobID)
{
    MyClient client = new MyClient(availableEndpoints[activeEndpointIndex].Name);
    client.GetUserInfoCompleted += (sender, args) => client_GetUserInfoCompleted(sender, args, fobID);
    client.GetUserInfoAsync(fobID);
}

static void client_GetUserInfoCompleted(object sender, GetUserInfoCompletedEventArgs e, string fobID)
{
    // access the additional parameter fobID here
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...