Функция реализации обратного вызова WCF никогда не вызывается - PullRequest
2 голосов
/ 29 марта 2012

Я разрабатываю службу WCF с обратным вызовом, но моя реализация функции обратного вызова никогда не вызывается. И я не совсем понимаю сгенерированный сервисный прокси, поэтому, пожалуйста, помогите.

Вот сценарий: на стороне сервера я определил интерфейс службы IMyService и интерфейс обратного вызова IMyServiceCallback, я также реализовал IMyService в проекте сервера. Помимо серверного проекта, у меня наверняка есть еще один клиентский проект, к которому я добавил ссылку на службу в VS. И я реализовал интерфейс IMyServiceCallback на стороне клиента. Таким образом, здесь возникает проблема: когда я отлаживаю его, функция никогда не входит в мою реализацию IMyServiceCallback и, конечно, желаемый результат никогда не выходит.

И вот тут я запутался: когда я добавил ссылку на службу на стороне клиента, она фактически сгенерировала три локальных интерфейса: IMyService, IMyServiceCallback и IMyServiceChannel плюс прокси-класс клиента. И в моей локальной реализации IMyServiceCallback я объявил класс для реализации локального интерфейса IMyServiceCallback, а не со стороны службы. Может ли это быть проблемой? Почему существуют два объявления интерфейса в разных проектах (и, следовательно, в разных пространствах имен)? Причина, по которой я реализую интерфейс на стороне клиента, заключается в том, что, если бы я реализовал интерфейс на стороне сервера, он выдает ошибку: «InstanceContext, предоставленный ChannelFactory, содержит объект UserObject, который не реализует ошибку CallbackContractType», когда я пытался вызвать службу. И еще одна сбивающая с толку часть: на стороне сервера, если я объявлю имя интерфейса обратного вызова как IMyCallback или что-то еще, вместо IMyServiceCallback, сгенерированный интерфейс на стороне клиента будет по-прежнему IMyServiceCallback, который является именем интерфейса службы плюс суффикс "Обратный звонок". И в этой ситуации я также получил «InstanceContext, предоставленный ChannelFactory, содержит UserObject, который не реализует ошибку CallbackContractType».

Полагаю, что я неправильно понял «добавить ссылку на сервис» и то, как я должен реализовать интерфейс (какой реализовать). Кто-нибудь может мне помочь? Спасибо!

Обновлен:

Я как-то исправил проблему. Во-первых, две декларации в порядке, желательно. Локальный клиент должен будет реализовать локальный интерфейс, который генерируется при добавлении ссылки на службу. И моя проблема заключалась в том, что я также определил DataContract, но в сгенерированном справочном файле его не было. Это может быть связано либо с тем, что я добавил сборку проекта службы в качестве ссылки (кто-то сказал, что в этом случае добавить ссылку на службу не будет генерировать Datacontract), либо из-за отсутствия атрибута DataMember. Но в любом случае, после того, как я исправил обе части, функция теперь работает.

Ответы [ 3 ]

2 голосов
/ 29 марта 2012

Когда вы «Добавить ссылку на службу» и создаете прокси, она полностью отделена от реализации вашей службы.Помните, что вы, возможно, используете сервис, который вы не написали и не имеете доступа к исходному коду сервиса.

Код клиента должен использовать сгенерированные клиентом интерфейсы.Если вы меняете службу, вам необходимо повторно создать прокси.

Если вы считаете, что это слишком грязно, и вы знаете, что всегда будете контролировать оба конца, вы можете совместно использовать интерфейсы службы в общей сборке и создать проксиКласс во время выполнения, используя DuplexChannelFactory.CreateChannel().

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

0 голосов
/ 30 января 2013

Я исправил проблему, когда моя инструкция обратного вызова была встроена в вызов функции. Я узнал, что размещение обратного вызова только в методе, который не возвращает результат, работает нормально. Однако, когда инструкция обратного вызова помещена в функцию, я столкнулся с проблемой тайм-аута.

Я решил это, используя поток фонового работника в вызываемой функции:

public static IMyServiceCallback Callback;
.
.
.

        TaskStateData taskStateData = GetSomeData();

        BackgroundWorker backgroundWorker = new BackgroundWorker();

        backgroundWorker.DoWork += (se, ev) =>
            {
                Tuple<OperationContext, TaskStateData> data = ev.Argument as Tuple<OperationContext, TaskStateData>;
                var operationContext = data.Item1;

                if (operationContext != null)
                {
                    Callback = operationContext.GetCallbackChannel<IMyServiceCallback>();
                    Callback.OnCallBack();
                }
            };

        Tuple<OperationContext, TaskStateData> payload = new Tuple<OperationContext, TaskStateData>(OperationContext.Current, taskStateData);
        backgroundWorker.RunWorkerAsync(payload);
0 голосов
/ 29 марта 2012

если вы хотите опубликовать, вы должны реализовать IMyServiceCallback и IMyService вместе в одном проекте.если вы только подписываетесь, вы должны реализовать интерфейс IMyServiceCallback

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