日期:2014-05-17 浏览次数:20873 次
在使用计划通知时,如果过于频繁的做一些获取或删除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