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

[CLK Framework] CLK.Threading.PortableTimer - 跨平台的Timer类别的更多相关文章

  1. [CLK Framework] CLK.Settings - 跨平台的参数存取模块

    [CLK Framework] CLK.Settings - 跨平台的参数存取模块 问题情景 开发功能模块的时候,常常免不了有一些参数(例如ConnectionString),需要存放在Config檔 ...

  2. [Architecture Design] CLK Architecture

    CLK.Prototype.Architecture 最近找数据,看到了博客园在不久之前,办了一个架构分享的活动:.Net项目分层与文件夹结构大全.看完之后觉得获益良多,接着也忍不住手痒,开始整理属于 ...

  3. Forms.Timer、Timers.Timer、Threading.Timer的研究

    .NET Framework里面提供了三种Timer System.Windows.Forms.Timer System.Timers.Timer System.Threading.Timer 一.S ...

  4. Microsoft Win32 to Microsoft .NET Framework API Map

    Microsoft Win32 to Microsoft .NET Framework API Map .NET Development (General) Technical Articles   ...

  5. .net Framework Class Library(FCL)

    from:http://msdn.microsoft.com/en-us/library/ms229335.aspx 我们平时在VS.net里引用的那些类库就是从这里来的 The .NET Frame ...

  6. System.Windows.Forms.Timer与System.Timers.Timer的区别(zz)

    .NET Framework里面提供了三种Timer: System.Windows.Forms.Timer System.Timers.Timer System.Threading.Timer VS ...

  7. 拥抱.NET Core,如何开发一个跨平台类库 (1)

    在此前的文章中详细介绍了使用.NET Core的基本知识,如果还没有看,可以先去了解“拥抱.NET Core,学习.NET Core的基础知识补遗”,以便接下来的阅读. 在本文将介绍如何配置类库项目支 ...

  8. [C#].NET中几种Timer的使用

    这篇博客将梳理一下.NET中4个Timer类,及其用法. 1. System.Threading.Timer public Timer(TimerCallback callback, object s ...

  9. .NET Core与.NET Framework、Mono之间的关系

    随着微软的.NET开源的推进,现在在.NET的实现上有了三个.NET Framework,Mono和.NET Core.经常被问起Mono的稳定性怎么样,后续Mono的前景如何,要回答这个问题就需要搞 ...

随机推荐

  1. 在Linux 应用层 基于i2c-dev.h 实现i2c读写

    /* i2c-dev.h - i2c-bus driver, char device interface Copyright (C) 1995-97 Simon G. Vogl Copyright ( ...

  2. 配置jenkins,并把iOS包自动上传至fir.im

    安装jenkins,有两种方式 1.首先要安装 homebrew,利用homebrew来管理安装包十分方便,一条命令就可以 安装 homebrew命令 $ ruby -e "$(curl - ...

  3. The file 'MemoryStream' is corrupted! 的解决办法

    The file 'MemoryStream' is corrupted! Remove it and launch unity again! [Position > ] 有时候我们会遇到这个报 ...

  4. python 字符串替换

    字符串替换可以用内置的方法和正则表达式完成.1用字符串本身的replace方法: a = 'hello word'b = a.replace('word','python')print b 2用正则表 ...

  5. php 将一个二维数组转换成有父子关系的数组

    <?php /** * Tree 树型类(无限分类) * * @author Kvoid * @copyright http://kvoid.com * @version 1.0 * @acce ...

  6. Javascript倒计时组件new TimeSpan(hours, minutes, minutes)

    function TimeSpan(h, m, s) { this.h = Number(h); this.m = Number(m); this.s = Number(s); } TimeSpan. ...

  7. 设计师必备!免费下载 PSD 素材的32个网站

    今天我想和大家分享一组可以免费下载 PSD 图形素材的最好的网站. PSD 文件是非常有用的资源,因为你可以看到所有的层,使用了什么技术来创建出这些作品和效果. 某些列出的网站可能已是众所周知的,但你 ...

  8. Xcode 报错信息

    1.CUICatalog: Invalid asset name supplied: 原因是: 使用的方法[UIImage imageNamed:@""]; @"&quo ...

  9. 通过Nginx实现负载均衡

    百度了下负载均衡:英文名称为Load Balance,其意思就是分摊到多个操作单元上进行执行,例如Web服务器.FTP服务器.企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务 嗯,跟我理 ...

  10. [Solution] ASP.NET Identity(1) 快速入门

    本节将介绍: ASP.NET Identity简介 快速入门 扩展 ASP.NET Identity简介 身份管理在ASP.NET中存在很长世间了,ASP.NET 开发团队已经学会了很多从客户的反馈. ...