2009-05-14 6 views
0

Мое приложение использует службу WCF net.tcp с каналом обратного вызова. По какой-то причине я не могу отправлять обратные вызовы на событие. Вот что я делаю (все кода на стороне сервера):Канал обратного вызова WCF преждевременно удаляется?

На инициализации:

OperationContext Context { get; protected set; } 
... 
Context = OperationContext.Current; 

На мероприятии:

var callback = Context.GetCallbackChannel<IServiceCallbackContract>(); 
callback.SomeMethod(); 

Это не будет работать на SomeMethod() с исключением следующего: {"Cannot access a disposed object.\r\nObject name: 'System.ServiceModel.Channels.ServiceChannel'."}

По-видимому, что-то располагает каналом обратного вызова, хотя клиент все еще способен разговаривать с сервером с помощью прямого (не обратного) канала. Это довольно странно. Какой объект я должен придерживаться, чтобы выполнить обратный вызов? Есть ли определенная цепочка, в которой это должно работать?

+0

Вы уверены, что сервис по-прежнему открыт, когда вы выполняете обратный вызов? – Gromer

ответ

0

Проблема была решена как моя ошибка. Обратные вызовы работали так, как они были разработаны, за исключением некоторых из них были устаревшими, которые при вызове бросали исключения. Так как я не попробовать/поймать их, целое событие разрывалось на этих черствых обратных вызовов :(.

Спасибо всем, кто попытался ответить на мой вопрос.

3

Configure Tracing и посмотрите, какое исключение вызывает неисправность вашего канала.

+0

хорошая идея ... дайте мне посмотреть, что он показывает – galets

2

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

1) Создайте новый класс, который будет содержать как мой запрос ввода, так и подтверждение для обратного вызова, например.

public struct MyCallbackDetails { 
    public MyCallbackDetails(IMyServiceCallback callback, RequestType request) : this() 
     Callback = callback; 
     Request = request; 
} 

public IMyServiceCallback Callback { get; set; } 

public RequestType request { get; set; } 
} 

2) Тогда я бы выстрелить отдельную нить пропускании MyCallbackDetails объект, а не только по запросу:

public ResponseType MyServiceMethod(RequestType request) { 
    //...Do Some Stuff 
    //Create MyCallbackDetails object to store reference to the callback and keep channel open 
    MyCallDetails callDetails = new MyCallDetails(OperationContext.Current.GetCallbackChannel<IMyServiceCallback>(), request); 
    //Fire off a new thread to call the BL and do some work 
    Thread processThread = new Thread(RunCallbackMethod); 
    processThread.Start(callDetails); 
} 

3) И мой RunCallbackMethod бы сделать вызов BL и ответить на обратный вызов.

void RunCallBackMethod(Object requestDetails) 
{ 
    //Use callbackdetails to make BL calls 
    MyCallbackDetails callDetails = (MyCallbackDetails)requestDetails; 
    // Make BL call - all code under here is syncrhonous 
    ResponseType response = BusinessLayer.BusinessMethod(callDetails.Request); 
    //NB: If your responsetype is a business object you will need to convert it to a service object 
    callDetails.Callback.SomeMethod(results); 
} 

NB: Да я уже покончили с наличием события из моего бизнеса слой огня обратно в служебный слой, однако, как я стреляя отдельную нить для бизнеса слоя она по-прежнему работает в асинхронном режиме и выполняет те же функции как если бы я вызывал BL прямо в ASync и ожидал, когда событие сообщит о его завершении.

PS: Благодаря Rory за идею и большую часть кода для реализации этого.

0

Вы пытались использовать OperationContext.Current непосредственно вместо переменной экземпляра Context?

+0

да, это нулевое значение, поскольку обратный вызов работает в другом потоке – galets

0

У меня была аналогичная проблема в моем чате приложение. Если Я закрыл свое приложение, а затем снова попытался открыть. Я все время получал Cannot access a disposed object при открытии канала.

Отслеживание назад через приложение Я сделал следующее, чтобы поразить основную причину.

  • Поместите точку останова в клиентское приложение, когда я завершаю вызов службы (выйдите из системы) перед закрытием. - Ничего не сообщать здесь.
  • Удаленная Отладка службы на сервере в методе выхода из системы. - Заметил, что обратный вызов не работал и генерировал исключение, потому что канал был удален по какой-либо причине.
  • Проверен атрибут OperationContract - найдена проблема!

Проблема заключалась в том, и эксперты WCF, поправьте меня, если я ошибаюсь, что OperationContract был как так

[OperationContract(IsInitiating = false, IsTerminating = true)] 
bool RemoveUser(Client user); 

Установка IsTerminating = true означает, что канал был закрыт до службы обрабатывал метод выхода из системы и поэтому, когда он пытался обратного вызова, он не мог.

Установка IsTerminating = false и закрытие канала на стороне клиента отсортировали проблему для меня.

В моем приложении обратный вызов не должен даже происходить, но это отдельная проблема все вместе и не связана. Главное, что если у вас есть IsTerminating = True, то убедитесь, что вы не используете обратный вызов.

Смежные вопросы