質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

4回答

3172閲覧

タイマーを用いた通知

shingi0326

総合スコア7

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

0グッド

1クリップ

投稿2018/04/15 11:09

前提・実現したいこと

現在業務でC#のWPFを使っています。
WPFの"Threading.Timer"というタイマー機能を使って、100ms毎に現在時刻と指定した時刻を比較して、指定した時刻になった時に別クラスの処理を実行するために通知を飛ばす仕組みを検討しています。
別クラスに通知して処理を実行するとするなら、イベントでの通知を思いつきましたが、どのように作ればいいのかイメージができていません。
良ければこのようなタイマー作りのアドバイスが欲しいです。
(イベント以外での通知方法もあれば嬉しいです。)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

この仕様だと、監視スレッドがずっと動いているのでかなり負荷は高くなります。
コメントを見ると 8 時とか 15 時とか間隔が大きいのでここまで厳しく監視する必要はないように思います。
また負荷が高い割には 100ms 毎というのは不正確です。

この仕様よりも、タイマーを目的の時間にセットしてイベントが起こるまで待機する方がいいのではないでしょうか。

次のコードを実行するとボタンクリックでタイマーが次の 8 時にセットされます。
時間が来ると「時間ですよ!」と表示され、それが 24 時間毎に行われます。
ここでは単純化のために timer1 Method1 という名前にしましたが、当然リストや配列を使ってください。
時間が来るまで負荷はほとんどありません。

C#

1static Timer timer1; 2 3private void Button_Click(object sender, RoutedEventArgs e) 4{ 5 // time1 に今日の 8 時までの時間を代入 6 var time1 = DateTime.Today + new TimeSpan(8, 0, 0) - DateTime.Now; 7 8 // 8 時過ぎていれば次の日の 8 時にする 9 if (time1 < TimeSpan.Zero) time1 += new TimeSpan(24, 0, 0); 10 11 // 時間になったらそこから 24 時間毎に Method1 を呼び出すようタイマーをセット 12 timer1 = new Timer(Method1, null, time1, new TimeSpan(24, 0, 0)); 13} 14 15private void Method1(object state) 16{ 17 MessageBox.Show($"時間ですよ!({DateTime.Now.ToString("HH:mm")})"); 18}

投稿2018/04/21 10:15

Zuishin

総合スコア28656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

イベント(デリゲート)を使った通知、でもいいですが、
manualreseteventなどを使って各スレッドに通知とかいうテもありますな

投稿2018/04/15 15:56

y_waiwai

総合スコア87719

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shingi0326

2018/04/16 15:09

ご回答ありがとうございます。 ざざっと調べてみたところ、別クラスに設けた処理を毎日指定した時刻に自動で実行させようと考えると、 対象にする処理がループさせた状態でmanualreseteventをかましてブロッキングとか 思い浮かべたのですが、愚直すぎますかね?
y_waiwai

2018/04/16 22:39

ループさせる必要あるならそうしたほうがいいでしょうけど、 ループの必要ないなら、待機させといて(眠らせておいて)指定時刻のイベントで復帰させる、のほうがいいんじゃ。 んでもひととつ、ループさせて、その中で指定時間を検出、とすると、最大そのループの実行時間分だけ実行が遅れることになるけど、それは許容できるんでしょうか
shingi0326

2018/04/17 15:14

下名の知識不足で申し訳ありませんが、待機させる仕組みがイメージがなかなかできません。 設定時刻と現在時刻を比較するために監視するループのことでしょうか? それでしたら、現在時刻が設定時刻を超えているかを判定するものを考えているので、大きな誤差が無ければ問題ないという認識です。 ループの頻度も100msと比較的に細かく監視するつもりです。
guest

0

ベストアンサー

こんなイメージでしょうか?
以下を参考に作ってみました。
https://qiita.com/hibara/items/9fd56a5d594c000a5df0

public delegate void イベント1ハンドラ(イベント1Arg e);
public delegate void イベント2ハンドラ(イベント2Arg e);

public event イベント1ハンドラ イベント1;
public event イベント2ハンドラ イベント2;

public コンストラクタ()
{
this.イベント1 += new this.イベント1ハンドラ(処理1);
this.イベント2 += new this.イベント2ハンドラ(処理2);

}

private void timer_callback()
{
if(指定時刻1)
{
イベント1(new イベント1Arg());
}

if(指定時刻2)
{
イベント2(new イベント2Arg());
}
}

private void 処理1(イベント1Arg e)
{
別Class.処理1();
}

private void 処理2(イベント2Arg e)
{
別Class.処理2();
}

投稿2018/04/25 04:55

tamina

総合スコア136

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

指定時刻と判定したら、別クラスのメソッドをコール
もしくは、別クラスでタイマー監視するとかじゃダメなんですか?

投稿2018/04/15 11:27

YAmaGNZ

総合スコア10222

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shingi0326

2018/04/15 12:17

ご回答ありがとうございます。 このタイマーの目的は、タイマー1つで複数の自動処理を通知して実行するものと考えています。 (処理1を15時、処理を8時に実行など) あと極力負荷を大きくしたくないなぁと考えるとこのタイマーでは設定時刻の監視と通知のみにしたいと考えています。(処理が10個以上あるので)
YAmaGNZ

2018/04/15 13:15

それなら、別クラスのメソッドを非同期メソッドとするなり、 そのメソッドで別スレッドを起こすなり手はあると思いますがどうでしょう?
shingi0326

2018/04/15 14:38

イメージすると、タイマーで行う自動処理を行うメソッドを非同期メソッドに置き換えたり、自動処理のメソッドを別スレッドで作成してタイマーからその別スレッドへ実行を呼びかけるというものでしょうか? 上手く汲み取れなくて申し訳ないです。
YAmaGNZ

2018/04/15 15:03

イメージは private void timer_callback(){ if(指定時刻){ 別Class.処理(); } } public class 別クラス{ public void 処理(){ //処理 } } のような感じで、もし、非同期である必要があるなら、別クラス側でどうにかすればよいのではないかと思います。
shingi0326

2018/04/16 15:16

その方法も検討しましたが、管理したい処理が10個以上あるので、100ms毎に10個も判定を行うと負荷が 大きくなってしまうのではないかと懸念しています。 また、別クラス側を何とかしたいのですが、既存の処理に手を出して他の処理や余計なバグを あまり出したくはないので、わがままなのは承知ですが、既存のクラスにはあまり手を出したくない状態です。 (あくまでもタイマー機能の追加のみをベースに考えています。)
YAmaGNZ

2018/04/16 22:16

どの方法を取るにしても、判定は必要だと思いますし、判定自体の負荷は無視してもよいかと思います。 既存クラスを修正したくないというのであれば、メソッドをコールする部分で別スレッドを生成するなりして、そのスレッドからメソッドをコールすればよいのではないですか?
shingi0326

2018/04/17 15:08

その方法で気になる点があるとすれば、タイマー関連での負荷が大きくならないかというところです。 既存の処理自体大きいものや通信処理を行うものもあるので、負荷を小さくするためにタイマーによる監視と通知を行う仕組みを考えています。 YAmaGNZさんのアドバイスですと、タイマー側で設定した処理も実行するように伺えるので、それで負荷が大きくならないか不安なところです。
YAmaGNZ

2018/04/17 22:06

だから、タイマーと同一スレッドで処理を行うのがダメなら、別スレッドを 起こせばどうかと書いている訳ですが、書き方が悪かったでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問