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

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

问题情景

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

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

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

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

解决方案

处理跨平台的定时执行功能,其实解决方案很简单,只要建立一个跨平台的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);
    
            }
    
        }
    
    }
    
    
  • 执行结果

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);
    
            }
    
        }
    
    }
    
    
  • 执行结果

你可能感兴趣的:(framework)