我有一个从 Microsoft 消息队列 ( netMsmqBinding
) 接收消息的 WCF 服务。
如果消息队列不可用,我希望我的服务能够恢复。我的代码应该无法打开服务,但在延迟后重试。
当队列不可用时,我有代码来识别错误:
static bool ExceptionIsBecauseMsmqNotStarted(TypeInitializationException ex)
{
MsmqException msmqException = ex.InnerException as MsmqException;
return ((msmqException != null) && msmqException.HResult == (unchecked((int)(0xc00e000b))));
}
所以这应该很简单:我调用ServiceHost.Open()
,捕获这个异常,等待一两秒钟,然后重复直到我的Open
调用成功。
问题是,如果这个异常被抛出一次,它会继续被抛出。消息队列可能已经可用,但我正在运行的进程处于错误状态,我会继续获取消息队列,TypeInitializationException
直到我关闭我的进程并重新启动它。
有没有办法解决这个问题?我可以让 WCF 原谅队列并真正尝试再听一遍吗?
这是我的服务开放代码:
public async void Start()
{
try
{
_log.Debug("Starting the data warehouse service");
while(!_cancellationTokenSource.IsCancellationRequested)
{
try
{
_serviceHost = new ServiceHost(_dataWarehouseWriter);
_serviceHost.Open();
return;
}
catch (TypeInitializationException ex)
{
_serviceHost.Abort();
if(!ExceptionIsBecauseMsmqNotStarted(ex))
{
throw;
}
}
await Task.Delay(1000, _cancellationTokenSource.Token);
}
}
catch (Exception ex)
{
_log.Error("Failed to start the service host", ex);
}
}
这是堆栈信息。第一次抛出内部异常的堆栈跟踪是:
在System.ServiceModel.Channels.MsmqQueue.GetMsmqInformation(版本和版本,布尔值和 activeDirectoryEnabled)
以及外部异常堆栈的顶部条目:
在System.ServiceModel.Channels.MsmqChannelListenerBase`1.get_TransportManagerTable()
在System.ServiceModel.Channels.TransportManagerContainer..ctor(TransportChannelListener 监听器)