За последний год я много узнал о 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
}