在AppPool循环后重新连接时,MVC5挂起在MapSignalR上

我在Startup.SignalR.cs中有以下代码:

using Microsoft.AspNet.SignalR; using Owin; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Admin { public partial class Startup { public void ConfigureSignalR(IAppBuilder app) { var Config = new HubConfiguration() { EnableDetailedErrors = false, Resolver = new DefaultDependencyResolver() }; #if DEBUG Config.EnableDetailedErrors = true; #endif // Any connection or hub wire up and configuration should go here app.MapSignalR(); GlobalHost.Configuration.ConnectionTimeout = TimeSpan.FromSeconds(600); } } } 

在应用程序的初始加载期间,一切都很顺利,但是当允许线程hibernate(离开约10分钟)时,AppPool被回收并且线程卡在此行上:

 app.MapSignalR(); 

IDE使用绿色箭头, This is the next statement to execute when this thread returns from the current function. 。 但是我不知道在这种情况下current function是什么。

尝试检查任何局部变量会导致Cannot evaluate expression because a native frame is on top of the call stack. 但是调用堆栈显示: Admin.dll!Admin.Startup.ConfigureSignalR(Owin.IAppBuilder app) Line 25作为顶部框架…

代码永远不会从此状态恢复,并且必须通过重新启动调试会话来完全重新启动AppPool。

有没有人对这种情况有任何解释?

附加信息:启用Debug => Windows => Parrallel Stacks后,我看到更详细的堆栈跟踪:

 [Managed to Native Transition] mscorlib.dll!Microsoft.Win32.RegistryKey.OpenSubKey(string name, bool writable) mscorlib.dll!Microsoft.Win32.RegistryKey.OpenSubKey(string name) System.dll!System.Diagnostics.PerformanceCounterLib.FindCustomCategory(string category, out System.Diagnostics.PerformanceCounterCategoryType categoryType) System.dll!System.Diagnostics.PerformanceCounterLib.IsCustomCategory(string machine, string category) System.dll!System.Diagnostics.PerformanceCounter.InitializeImpl() System.dll!System.Diagnostics.PerformanceCounter.PerformanceCounter(string categoryName, string counterName, string instanceName, bool readOnly) Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.Infrastructure.PerformanceCounterManager.LoadCounter(string categoryName, string counterName, string instanceName, bool isReadOnly) Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.Infrastructure.PerformanceCounterManager.LoadCounter(string categoryName, string counterName, bool isReadOnly) Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.Infrastructure.PerformanceCounterManager.SetCounterProperties() Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.Infrastructure.PerformanceCounterManager.Initialize(string instanceName, System.Threading.CancellationToken hostShutdownToken) Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.Hosting.HostDependencyResolverExtensions.InitializePerformanceCounters(Microsoft.AspNet.SignalR.IDependencyResolver resolver, string instanceName, System.Threading.CancellationToken hostShutdownToken) Microsoft.AspNet.SignalR.Core.dll!Microsoft.AspNet.SignalR.Hosting.HostDependencyResolverExtensions.InitializeHost(Microsoft.AspNet.SignalR.IDependencyResolver resolver, string instanceName, System.Threading.CancellationToken hostShutdownToken) Microsoft.AspNet.SignalR.Core.dll!Owin.OwinExtensions.UseSignalRMiddleware(Owin.IAppBuilder builder, object[] args) Microsoft.AspNet.SignalR.Core.dll!Owin.OwinExtensions.RunSignalR(Owin.IAppBuilder builder, Microsoft.AspNet.SignalR.HubConfiguration configuration) Microsoft.AspNet.SignalR.Core.dll!Owin.OwinExtensions.MapSignalR.AnonymousMethod__0(Owin.IAppBuilder subApp) Microsoft.Owin.dll!Owin.MapExtensions.Map(Owin.IAppBuilder app, Microsoft.Owin.PathString pathMatch, System.Action configuration) Microsoft.Owin.dll!Owin.MapExtensions.Map(Owin.IAppBuilder app, string pathMatch, System.Action configuration) Microsoft.AspNet.SignalR.Core.dll!Owin.OwinExtensions.MapSignalR(Owin.IAppBuilder builder, string path, Microsoft.AspNet.SignalR.HubConfiguration configuration) Microsoft.AspNet.SignalR.Core.dll!Owin.OwinExtensions.MapSignalR(Owin.IAppBuilder builder, Microsoft.AspNet.SignalR.HubConfiguration configuration) Microsoft.AspNet.SignalR.Core.dll!Owin.OwinExtensions.MapSignalR(Owin.IAppBuilder builder) Admin.dll!Admin.Startup.ConfigureSignalR(Owin.IAppBuilder app) Line 25 

另一个解决方案,来自这篇博文: http : //www.zpqrtbnk.net/posts/appdomains-threads-cultureinfos-and-paracetamol

 app.SanitizeThreadCulture(); public static void SanitizeThreadCulture(this IAppBuilder app) { var currentCulture = CultureInfo.CurrentCulture; // at the top of any culture should be the invariant culture, // find it doing an .Equals comparison ensure that we will // find it and not loop endlessly var invariantCulture = currentCulture; while (invariantCulture.Equals(CultureInfo.InvariantCulture) == false) invariantCulture = invariantCulture.Parent; if (ReferenceEquals(invariantCulture, CultureInfo.InvariantCulture)) return; var thread = Thread.CurrentThread; thread.CurrentCulture = CultureInfo.GetCultureInfo(thread.CurrentCulture.Name); thread.CurrentUICulture = CultureInfo.GetCultureInfo(thread.CurrentUICulture.Name); } 

正如Pawel所提到的,我能够通过使用虚拟性能计数器来解决我的问题,如下所示: https : //github.com/SignalR/SignalR/issues/3414

 // Global.asmx var tempCounterManager = new TempPerformanceCounterManager(); GlobalHost.DependencyResolver.Register(typeof (IPerformanceCounterManager), () => tempCounterManager); [....] // Helper Class public class TempPerformanceCounterManager : IPerformanceCounterManager { private readonly static PropertyInfo[] _counterProperties = GetCounterPropertyInfo(); private readonly static IPerformanceCounter _noOpCounter = new NoOpPerformanceCounter(); public TempPerformanceCounterManager() { foreach (var property in _counterProperties) { property.SetValue(this, new NoOpPerformanceCounter(), null); } } public void Initialize(string instanceName, CancellationToken hostShutdownToken) { } public IPerformanceCounter LoadCounter(string categoryName, string counterName, string instanceName, bool isReadOnly) { return _noOpCounter; } internal static PropertyInfo[] GetCounterPropertyInfo() { return typeof(TempPerformanceCounterManager) .GetProperties() .Where(p => p.PropertyType == typeof(IPerformanceCounter)) .ToArray(); } public IPerformanceCounter ConnectionsConnected { get; set; } public IPerformanceCounter ConnectionsReconnected { get; set; } public IPerformanceCounter ConnectionsDisconnected { get; set; } public IPerformanceCounter ConnectionsCurrentForeverFrame { get; private set; } public IPerformanceCounter ConnectionsCurrentLongPolling { get; private set; } public IPerformanceCounter ConnectionsCurrentServerSentEvents { get; private set; } public IPerformanceCounter ConnectionsCurrentWebSockets { get; private set; } public IPerformanceCounter ConnectionsCurrent { get; private set; } public IPerformanceCounter ConnectionMessagesReceivedTotal { get; private set; } public IPerformanceCounter ConnectionMessagesSentTotal { get; private set; } public IPerformanceCounter ConnectionMessagesReceivedPerSec { get; private set; } public IPerformanceCounter ConnectionMessagesSentPerSec { get; private set; } public IPerformanceCounter MessageBusMessagesReceivedTotal { get; private set; } public IPerformanceCounter MessageBusMessagesReceivedPerSec { get; private set; } public IPerformanceCounter ScaleoutMessageBusMessagesReceivedPerSec { get; private set; } public IPerformanceCounter MessageBusMessagesPublishedTotal { get; private set; } public IPerformanceCounter MessageBusMessagesPublishedPerSec { get; private set; } public IPerformanceCounter MessageBusSubscribersCurrent { get; private set; } public IPerformanceCounter MessageBusSubscribersTotal { get; private set; } public IPerformanceCounter MessageBusSubscribersPerSec { get; private set; } public IPerformanceCounter MessageBusAllocatedWorkers { get; private set; } public IPerformanceCounter MessageBusBusyWorkers { get; private set; } public IPerformanceCounter MessageBusTopicsCurrent { get; private set; } public IPerformanceCounter ErrorsAllTotal { get; private set; } public IPerformanceCounter ErrorsAllPerSec { get; private set; } public IPerformanceCounter ErrorsHubResolutionTotal { get; private set; } public IPerformanceCounter ErrorsHubResolutionPerSec { get; private set; } public IPerformanceCounter ErrorsHubInvocationTotal { get; private set; } public IPerformanceCounter ErrorsHubInvocationPerSec { get; private set; } public IPerformanceCounter ErrorsTransportTotal { get; private set; } public IPerformanceCounter ErrorsTransportPerSec { get; private set; } public IPerformanceCounter ScaleoutStreamCountTotal { get; private set; } public IPerformanceCounter ScaleoutStreamCountOpen { get; private set; } public IPerformanceCounter ScaleoutStreamCountBuffering { get; private set; } public IPerformanceCounter ScaleoutErrorsTotal { get; private set; } public IPerformanceCounter ScaleoutErrorsPerSec { get; private set; } public IPerformanceCounter ScaleoutSendQueueLength { get; private set; } } internal class NoOpPerformanceCounter : IPerformanceCounter { public string CounterName { get { return GetType().Name; } } public long Decrement() { return 0; } public long Increment() { return 0; } public long IncrementBy(long value) { return 0; } public long RawValue { get { return 0; } set { } } public void Close() { } public void RemoveInstance() { } public CounterSample NextSample() { return CounterSample.Empty; } } 

我在这里找到了解决方案:github.com/SignalR/SignalR/issues/3414 Snip sample:

 public void Configuration(IAppBuilder app) { var task = Task.Run(() => app.MapSignalR()); task.Wait(300); //try again if it fails just to be sure ;) if (task.IsCanceled) Task.Run(() => app.MapSignalR()).Wait(300); }