自托管 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 推送通知失败