由于对象未初始化(双工),WCF回调失败
本文关键字:WCF 回调 失败 双工 于对象 对象 初始化 | 更新日期: 2023-09-27 18:28:44
所以我有一个引发事件的对象和一个托管在windows服务中的WCF服务。
引发的事件当前在Windows服务中的一个类中,WCF服务订阅这些事件,当事件激发时,它们将作为客户端的回调,让客户端知道Windows服务的另一部分发生了什么。
问题是,有时回调有效,有时则无效。我要检查一下是否有客户可以回电,如果没有,我就不麻烦了。我不确定实现这一点的最佳方式是因为有时:
call = OperationContext.Current.GetCallbackChannel<IRiskEoDWCFEvents>();
在其他时候获取回调,该回调异常或设置为null,因为进入WCF服务的事件来自Windows服务(a类)的另一部分,而不是OperationContext。
简而言之如何设置WCF服务,以便在windows服务的另一部分发生事件时向客户端发出警报?
(更多代码)
在发布事件之前,我会做这样的检查(只有当我们有客户时才发布):
private void Publish(EoDEvent eodListEvent, EoDItem item)
{
if ( _EoDEventSubscribers == null || _EoDEventSubscribers.Count == 0)
{
//Cannot publish because we have no one listening
return;
}
.....
然后我就这样发布了:
Thread myThread = new Thread(myObject =>
{
lock (_SubscriberLock)
{
foreach (IRiskEoDWCFEvents callback in _EoDEventSubscribers)
{
if (callback.GetHashCode() != myObject.GetHashCode())
{
Logging.WriteLine("Sending event to {0}", callback.GetHashCode());
try
{
if (eodListEvent == EoDEvent.EoDComponentStarted)
callback.EoDComponentStarted(item);
else if (eodListEvent == EoDEvent.EoDComponentCompleted)
callback.EoDComponentCompleted(item);
.....
}
catch (Exception ex)
{
FaultException faultex = ex as FaultException;
if (faultex == null)
{
Logging.WriteLine("Callback failed, removing {0}", callback.GetHashCode());
toRemove.Add(callback);
}
}
}
}
if (toRemove.Count > 0)
{
foreach (IRiskEoDWCFEvents cb in toRemove)
{
_EoDEventSubscribers.Remove(cb);
}
}
}
});
myThread.Priority = ThreadPriority.Highest;
myThread.Start(call);
因此,我发现以下操作只是为了在foreach循环中获得回调并向客户端发送更新。
首先,我将呼叫设置为最新的用户
public void Subscribe()
{
IRiskEoDWCFEvents callback = OperationContext.Current.GetCallbackChannel<IRiskEoDWCFEvents>();
call = callback;
lock (_SubscriberLock)
{
if (!_EoDEventSubscribers.Contains(callback))
{
Logging.WriteLine("Adding callback {0}", callback.GetHashCode());
_EoDEventSubscribers.Add(callback);
}
}
}
然后,在发布方法上,我正在进行快速检查,试图将其设置为当前回调通道,但如果失败,只需获取一个我知道存在的通道:
if ( _EoDEventSubscribers == null || _EoDEventSubscribers.Count == 0)
{
//Cannot publish because we have no one listening
return;
}
if (call == null)
{
try
{
call = OperationContext.Current.GetCallbackChannel<IRiskEoDWCFEvents>();
}
catch
{
call = _EoDEventSubscribers[0];
}
}
虽然这是有效的,但我不确定这是否是最好的方法