我已经用MSMQ做了一些原型,并遇到了奇怪的行为。
我有 MSMQ 服务,当有消息进入队列时,该服务将数据发送到某个 Web 服务。我正在关闭 Web 服务并希望看到System.ServiceModel.ServerTooBusyException
,以便我的消息将返回到队列并在稍后发送。我正在控制台应用程序中托管 MSMQ 服务。
现在,如果我将数据同步发送到 Web 服务,那么我会得到预期的行为。如果我异步发送数据,我的控制台应用程序崩溃并出现未经处理的异常System.ServiceModel.ServerTooBusyException
。
这是伪代码:
安慰
AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
using (MSMQServiceHost serviceHost = new MSMQServiceHost(typeof(Service1)))
{
serviceHost.Open();
Console.WriteLine("Press any key to stop service...");
Console.ReadKey(true);
}
private static void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs)
{
MSMQ.Utils.LoggerHelper.GetLogger().ErrorFormat("CurrentDomainOnUnhandledException. {0}", unhandledExceptionEventArgs);
}
服务
[OperationBehavior(TransactionScopeRequired = true)]
public async void GetData(int start, int end)
{
try
{
using (WebServiceReference.Service1Client webClient = new WebServiceReference.Service1Client())
{
string data = await webClient.GetDataAsync(start);
//string data = webClient.GetData(start);
MSMQ.Utils.LoggerHelper.GetLogger().InfoFormat("Received info from web service. Datat{0}", data);
}
}
catch (Exception e)
{
MSMQ.Utils.LoggerHelper.GetLogger().ErrorFormat("{1}rn{0}", e.Message, e.GetType().FullName);
throw;
}
}
在同步调用的情况下,我会收到大量记录的错误,但应用程序没有崩溃。在异步调用的情况下,我得到相同的记录错误列表以及相同数量的 CurrentDomainOnUnhandledException(System.ServiceModel.ServerTooBusyException)
姆科利布.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.ThrowAsync.AnonymousMethod__5(对象状态)未知 姆科利布.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Unknown 姆科利布.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) 未知 姆科利布.dll!System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() 未知 姆科利布.dll!System.Threading.ThreadPoolWorkQueue.Dispatch() 未知
我的等待是可观察的 - 我已经订阅了 TaskScheduler.UnobservedTaskException,那里什么都没有。在这种情况下,如何正确使用异步,以便我从 APM 中获得所有好处并且我的应用程序不会崩溃?
我明白了。
问题出在我的服务操作中的async
修饰符上。正确版本:
[OperationBehavior(TransactionScopeRequired = true)]
public async Task GetData(int start, int end)
{
try
{
await Task.Factory.StartNew(() =>
{
using (WebServiceReference.Service1Client webClient = new WebServiceReference.Service1Client())
{
Task<string> data = GetWebClientData(start, webClient);
MSMQ.Utils.LoggerHelper.GetLogger().InfoFormat("Received info from web service. Datat{0}", data.Result);
}
}
}
catch (Exception e)
{
MSMQ.Utils.LoggerHelper.GetLogger().ErrorFormat("{1}rn{0}", e.Message, e.GetType().FullName);
throw;
}
}
private static async Task<string> GetWebClientData(int start, WebServiceReference.Service1Client webClient)
{
return await webClient.GetDataAsync(start);
}