Windows 7 Pro (32bit)
Microsoft Visual Studio 2017 Community
Sublime Text 2
DispatcherTimerを使ってAlarm機能を実装しようとした。
リンク
参考1: http://stackoverflow.com/questions/4946316/showing-difference-between-two-datetime-values-in-hours
v0.1
code
<Window x:Class="_170502_t0615_timer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:_170502_t0615_timer"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBlock Name="T_timer" FontSize="32" Text="00:00:00"/>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading; // for timer
namespace _170502_t0615_timer
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
DispatcherTimer myTimer;
public MainWindow()
{
InitializeComponent();
myTimer = new DispatcherTimer(DispatcherPriority.Normal);
myTimer.Interval = new TimeSpan(0, 0, 1);
myTimer.Tick += myTimer_Tick;
myTimer.Start();
}
void myTimer_Tick(object sender, EventArgs e)
{
T_timer.Text = DateTime.Now.ToLongTimeString();
var trigger = new DateTime(2017, 5, 2, 6, 27, 30);
TimeSpan diff = DateTime.Now.Subtract(trigger);
if (diff.Seconds == 0)
{
Console.WriteLine("Alarm");
}
Console.WriteLine("Tick");
}
}
}
結果
「出力」ウィンドウ。
...
Tick
Tick
Tick
Tick
Tick
Tick
Tick
Tick
Tick
Alarm
Tick
Alarm
Tick
Alarmが2回発行された。
バグっている。
v0.2
Alarm時の日時を表示するように変更。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading; // for timer
namespace _170502_t0615_timer
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
DispatcherTimer myTimer;
public MainWindow()
{
InitializeComponent();
myTimer = new DispatcherTimer(DispatcherPriority.Normal);
myTimer.Interval = new TimeSpan(0, 0, 1);
myTimer.Tick += myTimer_Tick;
myTimer.Start();
}
void myTimer_Tick(object sender, EventArgs e)
{
T_timer.Text = DateTime.Now.ToLongTimeString();
var trigger = new DateTime(2017, 5, 2, 6, 34, 30);
TimeSpan diff = DateTime.Now.Subtract(trigger);
if (diff.Seconds == 0)
{
Console.WriteLine("Alarm: on {0}", DateTime.Now.ToLongTimeString());
}
//Console.WriteLine("Tick");
}
}
}
Alarm: on 6:34:29
Alarm: on 6:34:30
Subtractしたときに1秒未満の誤差もdiff.Seconds==0
ということになっているようだ。
c++ builder > TDateTime > SecondsBetween() > 秒未満の切捨てに注意をする
と同じような感じなのだろう。
v0.3
diff.TotalSeconds()を表示してみた。
1つのAlarm時刻だけだと少ないため、複数のAlarm時刻にした。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading; // for timer
namespace _170502_t0615_timer
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
DispatcherTimer myTimer;
public MainWindow()
{
InitializeComponent();
myTimer = new DispatcherTimer(DispatcherPriority.Normal);
myTimer.Interval = new TimeSpan(0, 0, 1);
myTimer.Tick += myTimer_Tick;
myTimer.Start();
}
void myTimer_Tick(object sender, EventArgs e)
{
T_timer.Text = DateTime.Now.ToLongTimeString();
DateTime [] triggers = {
new DateTime(2017, 5, 2, 6, 44, 30),
new DateTime(2017, 5, 2, 6, 44, 32),
new DateTime(2017, 5, 2, 6, 44, 34),
};
TimeSpan diff;
foreach(var trg in triggers)
{
diff = DateTime.Now.Subtract(trg);
if (diff.Seconds == 0)
{
//Console.WriteLine("Alarm: on {0}", DateTime.Now.ToLongTimeString());
Console.WriteLine("Alarm: on {0}", diff.TotalSeconds.ToString());
}
}
//Console.WriteLine("Tick");
}
}
}
Alarm: on -0.9639294
Alarm: on 0.0581291
Alarm: on -0.9318132
Alarm: on 0.0782446
Alarm: on -0.9046972
Alarm: on 0.1103608
diff.TotalSecondsを0.1未満で切り捨てるのはだめのようだ。
v0.4 > 不等号使用案
http://stackoverflow.com/questions/10464743/is-there-a-better-way-to-set-an-alarm-clock-than-this
において不等号を使っている例があるのでそちらを使う。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading; // for timer
namespace _170502_t0615_timer
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
DispatcherTimer myTimer;
public MainWindow()
{
InitializeComponent();
myTimer = new DispatcherTimer(DispatcherPriority.Normal);
myTimer.Interval = new TimeSpan(0, 0, 1);
myTimer.Tick += myTimer_Tick;
myTimer.Start();
}
void myTimer_Tick(object sender, EventArgs e)
{
T_timer.Text = DateTime.Now.ToLongTimeString();
DateTime [] triggers = {
new DateTime(2017, 5, 2, 6, 51, 30),
new DateTime(2017, 5, 2, 6, 51, 32),
new DateTime(2017, 5, 2, 6, 51, 34),
};
foreach(var startdt in triggers)
{
var enddt = startdt.Add(new TimeSpan(0, 0, 1));
if (DateTime.Now >= startdt && DateTime.Now < enddt)
{
Console.WriteLine("Alarm: on {0}", DateTime.Now.ToLongTimeString());
}
}
//Console.WriteLine("Tick");
}
}
}
Alarm: on 6:51:30
Alarm: on 6:51:32
Alarm: on 6:51:34
成功したが、もっと良い方法は他にもありそうだ。
v0.5 > AddSeconds()
https://msdn.microsoft.com/ja-jp/library/system.datetime(v=vs.110).aspx
や過去の自分の記事を見ているとAddSeconds()というのが使えるようだ。
// var enddt = startdt.Add(new TimeSpan(0, 0, 1));
var enddt = startdt.AddSeconds(1);