В настоящее время я обновляю клиентское приложение, которое использует веб-службу 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));
}
}
}
}
}