Рекомендации по преобразованию вызовов WCF в асинхронные вызовы WCF
Автор вопроса: ScottGОтветов: 6
У меня возникают проблемы при попытке преобразовать все мои обычные вызовы WCF в асинхронные вызовы WCF. Я обнаружил, что у меня есть рефакторинг большого количества кода, и я не уверен, как именно это сделать. Я использовал метод, который нашел здесь, но столкнулся с проблемами, когда Мне нужно, чтобы все происходило по порядку.
Каков наилучший способ рефакторинга кода, чтобы он работал асинхронно, или мне нужно полностью переосмыслить свою логику? Мне действительно нужно повсюду вставлять счетчики и переключатели, чтобы убедиться, что определенные действия выполняются до того, как будут выполняться другие?
РЕДАКТИРОВАТЬ: причина, по которой я это делаю, заключается в том, что в ближайшие пару месяцев мы преобразуем это приложение WPF в Silverlight, для которого требуются асинхронные вызовы. Итак, я пытаюсь преобразовать наши обычные вызовы WCF в асинхронные в процессе подготовки. Я считаю, что это требует другого образа мышления.
Другими словами, кажется, что некоторые из ваших обязанностей могут быть неуместны - я обычно предпочитаю создавать службы, в которых я могу сделать один звонок к ним. Затем асинхронный характер не имеет значения, поскольку вы не выполняете последовательность событий.
Ответ 2 · рейтинг 2 · Matt Davis
Взгляните на Джувала Лоуи (автор книги Программирование служб WCF) веб-сайт с примерами реализации асинхронного программирования в ВКФ. Загрузки бесплатны; вам просто нужно указать свой адрес электронной почты.
Ответ 3 · рейтинг 1 · Navaar
Я, возможно, немного озадачен тем, почему вам нужно использовать асинхронные операции WCF, когда вам нужно, чтобы вещи были синхронными внутри цикла.
Если вы просто используете асинхронные методы, чтобы предотвратить зависание пользовательского интерфейса, вы можете просто использовать BackgroundWorker, который поддерживает обновления хода выполнения, чтобы поддерживать пользовательский интерфейс в актуальном состоянии, а не использовать асинхронные вызовы WCF.
Вы также должны иметь возможность вызывать различные функции из событий Completed для асинхронных методов.
Просто подключите обработчики событий к завершенным событиям, а затем передайте объект Item в качестве параметра userState при запуске асинхронного вызова WCF. Таким образом, вы будете иметь его в качестве параметра, когда срабатывает каждое из событий Completed. Таким образом, вы будете выполнять следующий шаг обработки только после завершения предыдущего асинхронного вызова.
Я не знаю, действительно ли это отвечает на ваш вопрос.
Если вы не используете Silverlight, вы можете заблокировать поток в одном методе до завершения других методов, например, с помощью события ManualResetEvent. Но это не будет работать в Silverlight, так как все вызовы WCF происходят в основном потоке пользовательского интерфейса, поэтому, если вы заблокируете этот поток, блокируется все. Лучший подход - сделать что-то подобное, используя обратные вызовы:
public delegate void OperationCallback();
private void btnSave_Click(object sender, RoutedEventArgs e)
{
List<Item> itemList = GetList();
foreach (Item i in itemList)
{
DoSomeWork(i, () =>
{
if (i.SomeID == 0)
{
DoSomeMoreWork(i, () =>
{
UpdateRecord(i);
});
}
else
{
UpdateRecord(i);
}
});
}
}
private void DoSomeWork(Item i, OperationCallback callback)
{
// call async method then callback when it completes.
callback();
}
private void DoSomeMoreWork(Item i, OperationCallback callback)
{
// call async method, then callback when it completes.
callback();
}
private void UpdateRecord(Item i)
{
// call async method
}
Это, конечно, не так ясно, как в синхронной версии, но если вы как можно больше используете лямбда-выражения, все же можно сохранить достаточно читаемый поток управления.
Ответ 6 · рейтинг -1 · Chris Porter
Добавьте 2 свойства в Item с именами SomeWorkDone и SomeMoreWorkDone как логические значения. Создайте методы для обработки как DoSomeWorkCompleted, так и DoSomeMoreWorkCompleted. В этих методах задайте для соответствующих логических свойств значение true и вызовите UpdateRecord. В UpdateRecord убедитесь, что оба свойства Done имеют значение true, а затем завершите вызовы.
У вас будут некоторые возможные проблемы с конкуренцией, но это должно помочь вам.