MVC5 hangs on MapSignalR when reconnecting after AppPool cycles

故事扮演 提交于 2019-11-30 17:32:33

another fix for this, from this blog post: 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);
}

As mentioned by Pawel, I was able to resolve my issue with the use of a dummy Performance Counter as documented here: 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;
    }
}

I found the solution here: 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);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!