2014-09-10 2 views
0

За последний год я много узнал о WCF, но поскольку я не использую его каждый день, я все еще знаю достаточно, чтобы быть опасным. Мой пример слишком усложнен, чтобы показать что-то, что иллюстрирует мою полную проблему, и я с удовольствием покажу фрагменты того, что у меня есть, что вы найдете полезным. У меня есть служба дуплекса и построена класс HostedTransactionServiceProcess, который инкапсулирует вызовы служб, чтобы любой класс уровня клиента, использующий это, не должен был понимать тонкости работы с WCF-сервисом. Услуга, в которую он инкапсулирует свои вызовы, также может связываться обратно через события обратного вызова. Проблема заключается в координации между операциями обслуживания и получением событий обратного вызова. Всякий раз, когда услуга callback вызывается службой, значения свойства/поля уровня класса для HostedTransactionServiceProcess равны нулю. Я думаю, что это имеет смысл, так как создание канала/прокси-сервера от Service-to-Client остается до Сервиса и не позволяет использовать столько элементов управления, которые мы имеем при создании канала/прокси-сервера, передающего от Client-to-Service. Поэтому, если он создает свой прокси-сервер обратного вызова, тогда все значения по умолчанию и его, как если бы эти значения никогда не изменялись.Поле класса обратного вызова WCF Null

Прежде всего, это правильно? Во-вторых, как мне обойти это?

Мне удалось обойти необходимость использования EventWaitHandle, создав именованный, который может работать между процессами, но мне все еще нужны другие свойства/данные поля в классе, которые будут отображаться между вызовами операций и вызовами вызова обратного вызова ,

Опять же, я могу предоставить больше информации по мере необходимости, просто дайте мне знать!

Редактировать: Я попытался упростить работу в неработоспособном классе, который должен хотя бы проиллюстрировать мою проблему. Может быть, это поможет?

[CallbackBehavior(UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Multiple, IncludeExceptionDetailInFaults = true)] 
public class HostedTransactionServiceProcess : ServiceProcess<IHostedTransactionService, HostedTransactionServiceInvoker, ConfigurationDuplexChannelFactory<IHostedTransactionService>>, IHostedTransactionServiceProcess, IHostedTransactionCallbackService 
{ 
    #region Properties 

    private ICADSession _cadSession; 

    public ICADSession CADSession 
    { 
     get { return _cadSession; } 
     set { _cadSession = value; } 
    } 


    #endregion 
    #region Operations 

    public void Commit(ICADSession cadSession, IEnumerable<IDTOEntity> dtoEntityCollection, IDTODocument dtoDocument, IDTOOperationLock operationLock) 
    { 

     lock (_serviceInvokerLock) 
     { 
      //Since the callback session will be instantiated by the WCF Service, any fields/properties in this class will be instantiated to null. 
      //This is because the Service is instantiating its own instance, creating its own proxy, based on the applied callback interface contract 
      //To work around this so that a call to the CAD System can wait until the CAD System responds back through the WCF Service, a named, inter-process 
      //EventWaitHandle will be used 
      using (EventWaitHandle waitHandle = ServiceWaitHandleHelper.StartNew(false, EventResetMode.AutoReset, cadSession, "Commit")) 
      { 
       //Set a local value... the issue is that this will end up null when the callback event is called!!!!! 
       //This seems to be because this instance making the Commit() call is different from the callback instance created to make the OnCommitted() call!!! 
       this.CADSession = cadSession; 

       //Make the proxy operation call 
       this.ServiceInvoker.Execute(serviceProxy => serviceProxy.Commit(cadSession, dtoEntityCollection, dtoDocument, operationLock)); 

       //The lock will not be released for the next Commit() operation call until the entire commit process is completed or the operation times out. 
       waitHandle.WaitOne(TimeSpan.FromMilliseconds(MAX_OPERATION_TIMEOUT)); 

      } 
     } 
    } 

    //The WCF Service Callback will call this 
    public void OnCommitted(ICADSession cadSession, IEnumerable<IDTOEntity> entityCollection, IDTODocument dtoDocument, IDTOOperationLock operationLock) 
    { 
     //First allow the Commit() operation to continue 
     EventWaitHandle waitHandle = ServiceWaitHandleHelper.GetExisting(cadSession, "Commit"); 
     if (waitHandle != null && this.CADSession == cadSession) //!!!!!! Here is the issue!!! Even though this.CADSession was set to a value, the callback instance says it is null!!! 
      waitHandle.Set(); 
     else 
      return; 
    } 

    #endregion 
} 

ответ

1

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

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