MVC5 hangs on MapSignalR when reconnecting after AppPool cycles

后端 未结 3 456
情书的邮戳
情书的邮戳 2021-01-04 04:44

I have the following code in my Startup.SignalR.cs:

using Microsoft.AspNet.SignalR;
using Owin;
using System;
using System.Collections.Generic;
using System.         


        
相关标签:
3条回答
  • 2021-01-04 05:27

    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;
        }
    }
    
    0 讨论(0)
  • 2021-01-04 05:37

    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);
    }
    
    0 讨论(0)
  • 2021-01-04 05:46

    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);
    }
    
    0 讨论(0)
提交回复
热议问题