日期:2014-05-17  浏览次数:20863 次

Windows8开发-处理计划通知Toast和使用Task

在使用计划通知时,如果过于频繁的做一些获取或删除Toast的操作,程序会抛出"无法找到元素"的异常。至于具体是什么原因,暂时搞不清楚。异常提供的信息实在有限。

不过Toast这些与UI交互并无多大关系数据,可以放到后台来处理,同时可以做一下访问频率的限制,从而减少抛出异常的几率。

使用后台线程的一大特点是,交互过程变得流畅了,而底层的一些数据可以在非UI线程中处理。可以怎么实现呢?本人是这么考虑的,首先逻辑代码放到Task.Run()中处理;同时维持一个是否正在处理Toast的标志和一个请求处理toast的列表。当有新的处理请求到达而程序块正在执行时,该请求就会被加入到请求列表中。当程序处理完一个请求之后,会从列表中查找下一个请求并执行,如果列表为空,该程序块就会退出。

下面是代码实现部分,其中Remove()函数使用了上面所说的机制。不过,此代码有一个很大的缺点,就是非线程安全的(m_IsProcessing并没有加锁):

using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.UI.Notifications;

namespace Test.NotificationService
{
    public class ScheduledActionService
    {
        #region Data Members

        // 标志是否正在处理请求
        private static bool m_IsProcessing = false;
        // 维持toast的处理请求列表
        private static List<string> m_ToastIds = new List<string>();

        #endregion

        #region Constructor

        private ScheduledActionService()
        {
        }

        #endregion

        #region Public Methos

        /// <summary>
        /// 添加toast计划通知
        /// </summary>
        public static void Add(ScheduledToastNotification notification)
        {
            Task.Run(() =>
                {
                    ToastNotificationManager.CreateToastNotifier().AddToSchedule(notification);
                });
        }

        /// <summary>
        /// 删除toast计划通知
        /// </summary>
        /// /// <param name="notification">指定的toast通知</param>
        public static void Remove(ScheduledToastNotification notification)
        {
            ToastNotificationManager.CreateToastNotifier().RemoveFromSchedule(notification);
        }

        /// <summary>
        /// 删除toast计划通知
        /// </summary>
        /// <param name="toastName">指定的toast通知的名字(id)</param>
        public static void Remove(string toastName)
        {
             Task.Run(() =>            
                {
                    m_ToastIds.Add(toastName);

                    if (m_IsProcessing)                      
                        return;
                    m_IsProcessing = true;

                    ToastNotifier notifier = ToastNotificationManager.CreateToastNotifier();
                    while (m_ToastIds.Count > 0)
                    {  
                        IReadOnlyList<ScheduledToastNotification> toasts = notifier.GetScheduledToastNotifications();
                        string toastId = m_ToastIds[0];
                        m_ToastIds.RemoveAt(0);

                        if (toasts.Count > 0)
                        {
                            foreach (var toast in toasts)
                            {
                                if (toast.Id == toastId)
                                    notifier.RemoveFromSchedule(toast);
                            }
                        }                       
                    }
                    m_IsProcessing = false;                    
                }
            );
        }

        /// <summary>
        /// 获取系统已有的计划通知数列表
        /// </summary>
        public static IReadOnlyList<ScheduledToastNotification> GetScheduledToastNotifications()
        {
            return ToastNotificationManager.CreateToastNotifier().GetScheduledToastNotifications();
        }

        public static IReadOnlyList<ScheduledToastNotification> Find(string toastName)
        {
            IReadOnlyList<ScheduledToastNotification> toasts = GetScheduledToastNotifications();
            List<ScheduledToastNotification> qualifiedToasts = new List<Schedul