自托管 pushsharp - Events_OnNotificationSendFailure 失败:线程池中没有足够的空闲线程来完成操作

Posted

技术标签:

【中文标题】自托管 pushsharp - Events_OnNotificationSendFailure 失败:线程池中没有足够的空闲线程来完成操作【英文标题】:self hosted pushsharp - Events_OnNotificationSendFailure Failure: There were not enough free threads in the ThreadPool to complete the operation 【发布时间】:2013-02-01 22:16:12 【问题描述】:

我的 PushSharp 服务是在 Windows 服务中自行托管的, 但过了一会儿它总是抛出: Events_OnNotificationSendFailure - 例外是“线程池中没有足够的空闲线程来完成操作”。什么是正确的方法?

public partial class PushNotificationService : ServiceBase

    private static bool flagNotification = true;
    static PushService push;


    protected override void OnStart(string[] args)
    
        SetPushService();

        //start console service worker
        Thread t = new Thread(NotificationServiceWorker);
        t.IsBackground = true;
        t.Start();
    

    private static void NotificationServiceWorker()
    
        try
        
            int sendNotificationTimeGap = Convert.ToInt32(ConfigurationManager.AppSettings["SendNotificationTimeGap"]);
            while (flagNotification)
            
                try
                
                    /// get iosPushNotificationService
                    IosPushNotificationService pns = new IosPushNotificationService();
                    /// Get The New Notification from db
                    List<NewPushNotifications> notificationToSend = pns.GetIosNotificationsToSend().Where(n => (n.CreatedDate ?? DateTime.Now) > DateTime.Now.AddMinutes(-5)).ToList();


                    if (notificationToSend != null && notificationToSend.Count > 0)
                    
                        SendNotificationToIphone(notificationToSend.Where(gn => gn.deviceType.Value == (int)DeviceType.Iphone).ToList());
                        SendNotificationToandroid(notificationToSend.Where(gn => gn.deviceType.Value == (int)DeviceType.Android).ToList());
                    

                    Thread.Sleep(sendNotificationTimeGap);
                
                catch (Exception ex)
                
                    CustomError.Error("error in flagNotification loop", ex);
                
            
        
        catch (Exception ex)
        
            CustomError.Error("error in NotificationServiceWorker", ex);
        
    

    private static void SetPushService()
    
        push = new PushService();

        push.Events.OnDeviceSubscriptionIdChanged += new PushSharp.Common.ChannelEvents.DeviceSubscriptionIdChanged(Events_OnDeviceSubscriptionIdChanged);
        push.Events.OnDeviceSubscriptionExpired += new PushSharp.Common.ChannelEvents.DeviceSubscriptionExpired(Events_OnDeviceSubscriptionExpired);
        push.Events.OnChannelException += new PushSharp.Common.ChannelEvents.ChannelExceptionDelegate(Events_OnChannelException);
        push.Events.OnNotificationSendFailure += new PushSharp.Common.ChannelEvents.NotificationSendFailureDelegate(Events_OnNotificationSendFailure);
        push.Events.OnNotificationSent += new PushSharp.Common.ChannelEvents.NotificationSentDelegate(Events_OnNotificationSent);

        string androidSenderId = ConfigurationManager.AppSettings["AndroidSenderId"];
        string androidSenderAuthToken = ConfigurationManager.AppSettings["AndroidSenderAuthToken"];
        string androidPackage = ConfigurationManager.AppSettings["androidPackage"];


        push.StartGoogleCloudMessagingPushService(new GcmPushChannelSettings(androidSenderId, androidSenderAuthToken, androidPackage), new PushSharp.Common.PushServiceSettings()  AutoScaleChannels = false );

        string appleCertificates = ConfigurationManager.AppSettings["AppleCertificates"];
        var appleCert = File.ReadAllBytes(appleCertificates);
        var appleCertPassword = ConfigurationManager.AppSettings["AppleCertPassword"];
        var appleIsProduction = ConfigurationManager.AppSettings["AppleIsProduction"].ToLower() == bool.TrueString;

        push.StartApplePushService(new ApplePushChannelSettings(appleIsProduction, appleCert, appleCertPassword));


    

【问题讨论】:

您是否尝试过调试它——检查有多少线程池线程,它们在做什么? 【参考方案1】:

不要使用线程,而是可以使用这样的计时器

protected override void OnStart(string[] args)
    
        NotificationServiceEventLog.WriteEntry("Service Started at"+DateTime.Now);

        if (oNotificationComponent ==null)
        oNotificationComponent = new NotificationComponent();

标题

        try
        

            if (StartAppleNotificationService())
                StartTimer();


        
        catch (Exception ex)
        

            NotificationServiceEventLog.WriteEntry(ex.Message);
        


       base.OnStart(args);
    

private bool StartAppleNotificationService()

        bool IsStarted = false;
        try
        

            if (oPushService == null)
            oPushService = new PushService();

            NotificationServiceEventLog.WriteEntry("Apple Notification Service started successfully");
            oPushService.Events.OnChannelCreated += new PushSharp.Common.ChannelEvents.ChannelCreatedDelegate(Events_OnChannelCreated);
            oPushService.Events.OnChannelDestroyed += new PushSharp.Common.ChannelEvents.ChannelDestroyedDelegate(Events_OnChannelDestroyed);
            oPushService.Events.OnChannelException += new PushSharp.Common.ChannelEvents.ChannelExceptionDelegate(Events_OnChannelException);
            oPushService.Events.OnDeviceSubscriptionExpired += new PushSharp.Common.ChannelEvents.DeviceSubscriptionExpired(Events_OnDeviceSubscriptionExpired);
            oPushService.Events.OnDeviceSubscriptionIdChanged += new PushSharp.Common.ChannelEvents.DeviceSubscriptionIdChanged(Events_OnDeviceSubscriptionIdChanged);
            oPushService.Events.OnNotificationSendFailure += new PushSharp.Common.ChannelEvents.NotificationSendFailureDelegate(Events_OnNotificationSendFailure);
            oPushService.Events.OnNotificationSent += new PushSharp.Common.ChannelEvents.NotificationSentDelegate(Events_OnNotificationSent);

            byte[] appleCert = File.ReadAllBytes("PushNSCert.p12");
            var settings = new ApplePushChannelSettings(true, appleCert, "123456");
            oPushService.StartApplePushService(settings);

            IsStarted = true;

        
        catch (Exception ex)
        

           throw new Exception("Exception in starting Apple Service :" + ex.Message + Environment.NewLine + ex.StackTrace);
        

        return IsStarted;
    
    private bool StartTimer() 


        try
        
            Double Ms = Convert.ToDouble(ConfigurationManager.AppSettings["TickInterval"]);
            NotificationServiceEventLog.WriteEntry("Time Interval" + Ms.ToString());
            MyTimer = new Timer();
            MyTimer.Interval += (1)*(60)*(1000);
            MyTimer.Enabled = true;
            MyTimer.Elapsed += new ElapsedEventHandler(ServiceTimer_Tick);
        
        catch (Exception ex) 

            throw ex;

        
        return true;
     
    private void ServiceTimer_Tick(object sender, System.Timers.ElapsedEventArgs e)
    
        string SentNotificationIDz = "";
        try
        
            MyTimer.Enabled = false;

            string szConnectionString = @"Server=.\SQL2K8;Database=PaychecksDB_Live;User Id=sa;Password=tdsadmin@321";
            //ConfigurationManager.AppSettings["connString"];

            lNotifictaion = oNotificationComponent.GetNotificationsList(szConnectionString);

            foreach (NotificationModel oNotificationModel in lNotifictaion)
            
                SendNotification(oNotificationModel.DeviceToken, oNotificationModel.NotificationMessage + " (" + oNotificationModel.NotificationTitle + ")");
                if (SentNotificationIDz == null)
                    SentNotificationIDz += oNotificationModel.Oid;
                else
                    SentNotificationIDz += "," + oNotificationModel.Oid;
            
            oNotificationComponent.DeleteSentNotifications(SentNotificationIDz, szConnectionString);
            MyTimer.Enabled = true;
        
        catch (Exception ex) 
            throw ex;
        

      //  
    
    private void SendNotification(string p_szDeviceToken,string p_szAlert)
    

        try
        

            oPushService.QueueNotification(NotificationFactory.Apple()
                                                      .ForDeviceToken(p_szDeviceToken)
                                                      .WithAlert(p_szAlert)
                                                      .WithBadge(2)
                                                      .WithSound("default")
                                                      .WithExpiry(DateTime.Now.AddDays(1))
                                                       );
        
        catch (Exception ex)
        
            throw new Exception("Error in sending Push Notification:" + ex.Message + Environment.NewLine + ex.StackTrace);
        
    

【讨论】:

谢谢,我会试试的。这就是您在生产中使用 pushsharp 的方式吗? 我不是 .net/c# 开发人员,但这看起来很糟糕的设计

以上是关于自托管 pushsharp - Events_OnNotificationSendFailure 失败:线程池中没有足够的空闲线程来完成操作的主要内容,如果未能解决你的问题,请参考以下文章

带有自定义声音的 PushSharp iOS PushNotification

使用 Redth PushSharp 发送 iOS 推送通知失败

PushSharp 是不是支持 windows phone 8.1 推送通知?

Pushsharp 连接失败

PushSharp 通知错误

PushSharp:'DeviceSubscriptionChanged',我该怎么办?