У меня такое ощущение, что должно быть лучшее решение, чем то, что я придумал; вот в чем проблема:WPF/WCF Асинхронный сервис Call and SynchronizationContext
Форма WPF вызовет метод WCF, который возвращает bool. Сам вызов не должен находиться в потоке пользовательского интерфейса, и результат вызова должен отображаться в форме, поэтому возврат должен быть привязан к потоку пользовательского интерфейса.
В этом примере я создал класс «ServiceGateway», которому форма передаст метод, который будет выполнен после завершения операции входа. Шлюз должен вызывать этот делегат, заполняющий логин, с использованием интерфейса синхронизации UI, который передается при создании шлюза из формы. Метод Login вызывает вызов _proxy.Login с использованием anon. асинхронному делегат, а затем предоставляет функцию обратного вызова, который вызывает делегату («обратного вызова» параметры), приведенные к шлюзу (из формы) с помощью пользовательского интерфейса SynchronizationContext:
[CallbackBehavior(UseSynchronizationContext = false)]
public class ChatServiceGateway : MessagingServiceCallback
{
private MessagingServiceClient _proxy;
private SynchronizationContext _uiSyncContext;
public ChatServiceGateway(SynchronizationContext UISyncContext)
{
_proxy = new MessagingServiceClient(new InstanceContext(this));
_proxy.Open();
_uiSyncContext = UISyncContext;
}
public void Login(String UserName, Action<bool> callback)
{
new Func<bool>(() => _proxy.Login(UserName)).BeginInvoke(delegate(IAsyncResult result)
{
bool LoginResult = ((Func<bool>)((AsyncResult)result).AsyncDelegate).EndInvoke(result);
_uiSyncContext.Send(new SendOrPostCallback(obj => callback(LoginResult)), null);
}, null);
}
Метод Логина вызывается из формы в ответ на событие нажатия кнопки.
Это прекрасно работает, но у меня есть подозрение, что я ошибаюсь в методе входа; особенно потому, что мне придется сделать то же самое для любого другого вызова метода для службы WCF, и его уродливость.
Я хотел бы сохранить асинхронное поведение и синхронизацию ui, инкапсулированную в шлюз. Было бы лучше иметь асинхронное поведение, реализованное на стороне WCF? В принципе, меня интересует, могу ли я реализовать вышеприведенный код более универсально для других методов или если все будет лучше.
Вы должны иметь возможность повторно создать клиент WCF с асинхронными API-интерфейсами на основе 'Task', что значительно облегчит их очистку. –