• [CLK Framework] CLK.Threading.PortableTimer


    [CLK Framework] CLK.Threading.PortableTimer - 跨平台的Timer类别

    问题情景

    开发应用程式的时候,免不了需要加入一些定时执行的设计,例如说:定时更新画面资料、定时检查资料库内容、定时检查通讯是否断线...等等。而.NET Framework也很贴心的提供三种不同的Timer类别,用来帮助开发人员设计出定时执行的功能模组。

    .NET Framework提供的三种Timer类别,可以参考Bill叔的部落格:

    但是当功能模组的开发,是以跨平台执行为目标来做设计的时候,因为不是每个平台都支援上列三种Timer,所以连带的在跨平台的专案中,也就不支援参考使用.NET Framework所提供的Timer类别。像是下图中所建立的Portable Class Library专案,就无法参考使用到System.Threading.Timer类别。

    遇到这样跨平台的功能模组开发,该如何提供跨平台的定时执行功能呢?

    问题情景01

    解决方案

    处理跨平台的定时执行功能,其实解决方案很简单,只要建立一个跨平台的Timer类别,用来提供定时执行的功能,就可以满足这个设计需求。

    模组设计

    建立Timer类别最简单的设计,就是开启一条独立的执行绪,透过这个执行绪定时去执行Callback函式,这就完成了Timer类别的功能设计。但是因为.NET Framework中所提供的System.Threading.Thread并不支援跨平台使用。所以执行绪的建立工作,必须改为可以跨平台使用的System.Threading.Tasks.Task来建立执行绪,这样才能符合跨平台的开发需求。

    使用跨平台的System.Threading.Tasks.Task类别来建立的执行绪,并且使用这个执行绪来定时执行Callback函式,这就完成了跨平台Timer类别的功能设计。

    模组下载

    程式码下载:由此进入GitHub后,点选右下角的「Download ZIP」按钮下载。

    (开启程式码的时候,建议使用Visual Studio所提供的「大纲->折叠至定义」功能来折叠程式码,以能得到较适合阅读的排版样式。)

    物件程式

    using CLK.Diagnostics;
    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace CLK.Threading
    {
        public sealed class PortableTimer : IDisposable
        {
            // Fields
            private readonly ManualResetEvent _executeThreadEvent = new ManualResetEvent(false);
    
            private readonly Action _callback = null;
    
            private readonly int _interval = 0;
    
    
            // Constructors
            public PortableTimer(Action callback, int interval)
            {
                #region Contracts
    
                if (callback == null) throw new ArgumentNullException();
    
                #endregion
    
                // Require
                if (interval <= 0) throw new ArgumentException();
    
                // Arguments
                _callback = callback;
                _interval = interval;
    
                // Begin
                Task.Factory.StartNew(this.Execute);
            }
    
            public void Dispose()
            {
                // End
                _executeThreadEvent.Set();
            }
    
    
            // Methods
            private void Execute()
            {
                while (true)
                {
                    // Wait
                    if (_executeThreadEvent.WaitOne(_interval) == true)
                    {
                        return;
                    }
    
                    // Execute
                    try
                    {
                        // Callback
                        _callback();
                    }
                    catch (Exception ex)
                    {
                        // Fail
                        DebugContext.Current.Fail(string.Format("Action:{0}, State:{1}, Message:{2}", "Callback", "Exception", ex.Message));
                    }
                }
            }
        }
    }
    

    使用范例

    CLK.Threading.Samples.No001 - 在Windows Store App中使用PortableTimer

    • 使用范例

      using System;
      using System.Threading;
      using Windows.UI.Xaml;
      using Windows.UI.Xaml.Controls;
      
      namespace CLK.Threading.Samples.No001
      {
          public sealed partial class MainPage : Page
          {
              // Fields
              private readonly object _syncRoot = new object();
      
              private readonly SynchronizationContext _syncContext = null;
      
              private PortableTimer _operateTimer = null;
      
      
              // Constructors
              public MainPage()
              {
                  // Base
                  this.InitializeComponent();
      
                  // SyncContext
                  _syncContext = SynchronizationContext.Current;
              }
      
      
              // Handlers
              private void MainPage_Loaded(object sender, RoutedEventArgs e)
              {
                  lock (_syncRoot)
                  {
                      // Require
                      if (_operateTimer != null) return;
      
                      // Begin
                      _operateTimer = new PortableTimer(this.Timer_Ticked, 500);
                  }
              }
      
              private void MainPage_Unloaded(object sender, RoutedEventArgs e)
              {
                  lock (_syncRoot)
                  {
                      // Require
                      if (_operateTimer == null) return;
      
                      // End
                      _operateTimer.Dispose();
                      _operateTimer = null;
                  }
              }
      
              private void Timer_Ticked()
              {
                  System.Threading.SendOrPostCallback methodDelegate = delegate(object state)
                  {
                      // Display
                      this.TextBlock001.Text = DateTime.Now.ToString();
                  };
                  _syncContext.Post(methodDelegate, null);
              }
          }
      }
      
    • 执行结果

      使用范例01

    CLK.Threading.Samples.No002 - 在Windows Phone App中使用PortableTimer

    • 使用范例

      using System;
      using System.Windows;
      using Microsoft.P​​hone.Controls;
      using System.Threading;
      
      namespace CLK.Threading.Samples.No002
      {
          public partial class MainPage : PhoneApplicationPage
          {
              // Fields
              private readonly object _syncRoot = new object();
      
              private readonly SynchronizationContext _syncContext = null;
      
              private PortableTimer _operateTimer = null;
      
      
              // Constructors
              public MainPage()
              {
                  // Base
                  this.InitializeComponent();
      
                  // SyncContext
                  _syncContext = SynchronizationContext.Current;
              }
      
      
              // Handlers
              private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
              {
                  lock (_syncRoot)
                  {
                      // Require
                      if (_operateTimer != null) return;
      
                      // Begin
                      _operateTimer = new PortableTimer(this.Timer_Ticked, 500);
                  }
              }
      
              private void PhoneApplicationPage_Unloaded(object sender, RoutedEventArgs e)
              {
                  lock (_syncRoot)
                  {
                      // Require
                      if (_operateTimer == null) return;
      
                      // End
                      _operateTimer.Dispose();
                      _operateTimer = null;
                  }
              }
      
              private void Timer_Ticked()
              {
                  System.Threading.SendOrPostCallback methodDelegate = delegate(object state)
                  {
                      // Display
                      this.TextBlock001.Text = DateTime.Now.ToString();
                  };
                  _syncContext.Post(methodDelegate, null);
              }
          }
      }
      
    • 执行结果

    CLK.Threading.Samples.No003 - 在WPF中使用PortableTimer

    • 使用范例

      using System;
      using System.Threading;
      using System.Windows;
      
      namespace CLK.Threading.Samples.No003
      {
          public partial class MainWindow : Window
          {
              // Fields
              private readonly object _syncRoot = new object();
      
              private readonly SynchronizationContext _syncContext = null;
      
              private PortableTimer _operateTimer = null;
      
      
              // Constructors
              public MainWindow()
              {
                  // Base
                  this.InitializeComponent();
      
                  // SyncContext
                  _syncContext = SynchronizationContext.Current;
              }
      
      
              // Handlers
              private void Window_Loaded(object sender, RoutedEventArgs e)
              {
                  lock (_syncRoot)
                  {
                      // Require
                      if (_operateTimer != null) return;
      
                      // Begin
                      _operateTimer = new PortableTimer(this.Timer_Ticked, 500);
                  }
              }
      
              private void Window_Unloaded(object sender, RoutedEventArgs e)
              {
                  lock (_syncRoot)
                  {
                      // Require
                      if (_operateTimer == null) return;
      
                      // End
                      _operateTimer.Dispose();
                      _operateTimer = null;
                  }
              }
      
              private void Timer_Ticked()
              {
                  System.Threading.SendOrPostCallback methodDelegate = delegate(object state)
                  {
                      // Display
                      this.TextBlock001.Text = DateTime.Now.ToString();
                  };
                  _syncContext.Post(methodDelegate, null);
              }
          }
      }
      
    • 执行结果

      使用范例03

  • 相关阅读:
    jquery仿淘宝规格颜色选择效果
    JQuery实现的模块交换动画效果
    javascript检查移动设备是否支持重力方向感应
    Mysql数据库备份和还原常用的命令
    Mysql备份还原数据库之mysqldump实例及参数详细说明
    php抽象类和接口
    Ubuntu下lamp(PHP+Mysql+Apache)搭建+完全卸载卸载方法
    Ubuntu 麒麟版下安装:Apache+php5+mysql+phpmyadmin.
    Ubuntu下安装Wine&WineQQ+Phpstorm+wps+svn+vim(计划任的使用)+flashplayer+curl扩展
    GitHub Linux下使用方法
  • 原文地址:https://www.cnblogs.com/clark159/p/3440401.html
Copyright © 2020-2023  润新知