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

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

ただいまの
回答率

90.84%

  • C#

    5981questions

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

  • WPF

    626questions

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

タイマーを用いた通知

解決済

回答 4

投稿

  • 評価
  • クリップ 1
  • VIEW 297

shingi0326

score 1

 前提・実現したいこと

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+2

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

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

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

static Timer timer1;

private void Button_Click(object sender, RoutedEventArgs e)
{
    // time1 に今日の 8 時までの時間を代入
    var time1 = DateTime.Today + new TimeSpan(8, 0, 0) - DateTime.Now;

    // 8 時過ぎていれば次の日の 8 時にする
    if (time1 < TimeSpan.Zero) time1 += new TimeSpan(24, 0, 0);

    // 時間になったらそこから 24 時間毎に Method1 を呼び出すようタイマーをセット
    timer1 = new Timer(Method1, null, time1, new TimeSpan(24, 0, 0));
}

private void Method1(object state)
{
    MessageBox.Show($"時間ですよ!({DateTime.Now.ToString("HH:mm")})");
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

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();
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/15 21:17

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

    キャンセル

  • 2018/04/15 22:15

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

    キャンセル

  • 2018/04/15 23:38

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

    キャンセル

  • 2018/04/16 00:03

    イメージは

    private void timer_callback(){
    if(指定時刻){
    別Class.処理();
    }
    }

    public class 別クラス{
    public void 処理(){
    //処理
    }
    }

    のような感じで、もし、非同期である必要があるなら、別クラス側でどうにかすればよいのではないかと思います。

    キャンセル

  • 2018/04/17 00:16

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

    キャンセル

  • 2018/04/17 07:16

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

    キャンセル

  • 2018/04/18 00:08

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

    キャンセル

  • 2018/04/18 07:06

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

    キャンセル

0

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/17 00:09

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

    キャンセル

  • 2018/04/17 07:39

    ループさせる必要あるならそうしたほうがいいでしょうけど、
    ループの必要ないなら、待機させといて(眠らせておいて)指定時刻のイベントで復帰させる、のほうがいいんじゃ。

    んでもひととつ、ループさせて、その中で指定時間を検出、とすると、最大そのループの実行時間分だけ実行が遅れることになるけど、それは許容できるんでしょうか

    キャンセル

  • 2018/04/18 00:14

    下名の知識不足で申し訳ありませんが、待機させる仕組みがイメージがなかなかできません。

    設定時刻と現在時刻を比較するために監視するループのことでしょうか?
    それでしたら、現在時刻が設定時刻を超えているかを判定するものを考えているので、大きな誤差が無ければ問題ないという認識です。
    ループの頻度も100msと比較的に細かく監視するつもりです。

    キャンセル

  • 2018/04/18 08:05

    https://www.ipentec.com/document/csharp-wait-thread-proc-block

    ManualResetEvent の WaitOne メソッドにより
    スレッドを待機させておき、別のところからの通知からスレッドを復帰させるというのが可能です

    キャンセル

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

  • ただいまの回答率 90.84%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C#

    5981questions

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

  • WPF

    626questions

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