[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. IIS+PHP+MYSQL安装配置

    首先下载php-5.2.0-win32.zip,mysql-noinstall-5.0.22-win32.zip和phpMyAdmin-2.9.1.1-all-languages.zip.这三个文件的 ...

  2. 碰到一个在app内部浏览器锚点异常的问题

    最近在做一个文章评论的功能,其中一个需求是:在提交完评论后,需要跳转到位于页面底部的评论区域,正常情况下location.href=http://m.hostname.cn/article#comme ...

  3. preg_match_all正则表达式的基本使用

    了解正则表达式之前,须要掌握一些常用的正则表达式的基础知识,这些如果能记得最好记得,记不住须要用的时候能查到就行,就多个特殊字符,所以说正则表达式玩的就是特殊,具体大家可以查看更加细致的说明. pre ...

  4. WCF的传输安全(读书笔记)

    Wcf的传输安全主要涉及认证.消息的一致性和机密性.Wcf采用两种不同的机制来解决这三个涉及传输安全的问题,即Transport安全模式和Message安全模式. Transport安全模式利用基于传 ...

  5. 用户Word写毕业论文时的文献引用方法

    经过网上搜索和自己实践,找到了一种不用第三方工具的文献管理方法 通过将文献定义的成书签的形式,插入到文献中,当文献编号发生变化时,只需进行更新域操作,就可实现文献编号的理新,下面介绍具体方法: 1.首 ...

  6. 《Programming with Objective-C》第三章 Working with Objects

    Object和普通变量的区别 If you’re used to using terms like the stack and the heap, a local variable is alloca ...

  7. Java知多少(105)套接字(Socket)

    网络应用模式主要有: 主机/终端模式:集中计算,集中管理: 客户机/服务器(Client/Server,简称C/S)模式:分布计算,分布管理: 浏览器/服务器模式:利用Internet跨平台. www ...

  8. MFC ADO连接Oracle12c数据库 类库文件

    Stdafx.h Stdafx.h libado.h libado.h libado.cpp libado.cpp 参考网址如下:http://www.cnblogs.com/livewithnore ...

  9. WCF小白初试 错误之一:“有零个应用程序终结点”的解决办法

    遇到这类问题 应该是配置文件出现了问题 解决办法是将配置文件中的<service name="命名空间+类名">就可以解决

  10. jQuery+Ajax滚屏异步加载数据实现(附源码)

    一.CSS样式 body { font:12px/1.0em Microsoft Yahei; line-height:1.6em; background:#fff; line-height:1.2e ...