WCF服务回调类字段为Null
本文关键字:Null 字段 服务 回调 WCF | 更新日期: 2023-09-27 18:21:16
在过去的一年里,我学到了很多关于WCF的知识,但由于我不是每天都使用它,我仍然知道它很危险。我的例子太复杂了,无法展示能说明我全部问题的东西,我很乐意展示我所拥有的那些你会觉得有用的部分。我有一个双工服务,并构建了一个名为HostedTransactionServiceProcess的类,该类封装了服务调用,这样任何使用它的客户端级类都不必理解使用WCF服务的复杂性。它封装调用的服务也可以通过回调事件进行通信。问题往往是服务操作和接收回调事件之间的协调。每当服务调用回调事件时,HostedTransactionServiceProcess的类级属性/字段值都为null。我认为这是有道理的,因为创建从服务到客户端的通道/代理留给了服务,并且在创建从客户端到服务的通道/代理人时不允许我们有那么多的控制。因此,如果它实例化了回调代理,那么一切都会默认,就好像这些值从未被修改过一样。
首先,这是正确的吗?其次,我该如何解决它?
我能够通过创建一个可以在进程间工作的命名EventWaitHandle来解决使用EventWaitHandler的需求,但我仍然需要在操作调用和回调事件调用之间看到类中的其他属性/字段数据。
再次,我可以根据需要提供更多信息,只需让我知道!
编辑:我试图将事情简化为一个不可行的类,至少应该说明我的问题。也许这会有所帮助?
[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
}
我想我已经回答了自己的问题。我基本上有服务和两个客户。似乎正在调用回调事件,但字段值为null。在调试时,我验证了它正在订阅回调,所以它让我抓狂。然后我发现一个客户端的回调被调用了,但另一个客户端没有被调用。事实证明,尽管它捕获了回调通道,但它在同一线程上的前一个方法完成之前进行了回调。。。僵局因此,我在一个独立的线程上开始了与该事件的连接和注册,而不是启动该进程的操作调用,现在它似乎可以工作了。