処理の複数の実行を待機させるには

タグの編集
投稿者 はるお  (社会人) 投稿日時 2020/3/22 19:44:42
お世話になっております、はるおと申します。

処理の実行を指定秒数待機させたいです。

例:Aボタン押下時、B処理を30分後に実行。Cボタン押下時、D処理を50分後に実行。

この場合、Timerイベントを扱わず、それぞれの処理を時間経過で実行させたいのですが
良い案が浮かびません。

システム日付の時間をTimerイベント以外でシステム日付の推移を読み取り、指定の分数で
処理を実行させることができないかと調べてみましたが、システム日付の推移を取得できそうな
イベントなどはなく、それならSleepメソッドで出来るかと思い、試してみましたがAボタン押下の段階でメインフォームをスリープさせてしまい、Cボタンを押すことが出来ません。

Timerイベント以外で実現できる方法などはあるのでしょうか。

よろしくお願いいたします。
投稿者 るきお  (社会人) 投稿日時 2020/3/22 21:28:48
たとえば、こんな感じでしょうか。30分待つのは大変なので、仮に30秒にしました。
Private Sub buttonA_Click(sender As Object, e As EventArgs) Handles buttonA.Click
    '30秒後にTickイベントを発生させるタイマーを作成。 
    Dim timer As New Timer With {.Interval = 30 * 1000, .Enabled = True}

    '非同期でProcessBを実行する処理を作成し、Tickイベント時に実行するようにしておく。 
    Dim task As New Task(Sub() ProcessB(timer))
    AddHandler timer.Tick, Sub(s, args) task.Start()

End Sub

Private Sub ProcessB(timer As Timer)
    timer.Enabled = False
    timer.Dispose()

    MsgBox("処理Bを実行しました。")
End Sub

Private Sub buttonC_Click(sender As Object, e As EventArgs) Handles buttonC.Click

    '50秒後にTickイベントを発生させるタイマーを作成。 
    Dim timer As New Timer With {.Interval = 50 * 1000, .Enabled = True}

    '非同期でProcessDを実行する処理を作成し、Tickイベント時に実行するようにしておく。 
    Dim task As New Task(Sub() ProcessD(timer))
    AddHandler timer.Tick, Sub(s, args) task.Start()

End Sub

Private Sub ProcessD(timer As Timer)
    timer.Enabled = False
    timer.Dispose()

    MsgBox("処理Dを実行しました。")
End Sub


でも、この機能だけ見るとウィンドウを閉じられたらすべてが終わってしまいますし、処理Bで想定外のエラーが発生してプログラムが終了してしまうと、その後実行される予定だった処理Dが巻き添えを食って実行されなくなるなど、あまり構造が良くないように思います。

Windowsのタスクスケジューラーでも似たようなことができるのでそちらの利用を検討されてはどうでしょうか?

非同期で実行する処理B、処理Dもこの例では非常にシンプルな処理なのでこれで済んでいますが、戻り値やエラーハンドリングや、UIの更新などいろいろ考え出すととても大変です。とても人に薦められるプログラムではありません。
投稿者 るきお  (社会人) 投稿日時 2020/3/22 21:50:07
そういえば、こうするともっとすっきり書けます。
しかし、前の投稿と同じ理由でお勧めはできません。
Private Sub buttonA_Click(sender As Object, e As EventArgs) Handles buttonA.Click
    Task.Delay(30 * 1000).ContinueWith(Sub() ProcessB())
End Sub

Private Sub ProcessB()
    MsgBox("処理Bを実行しました。")
End Sub

Private Sub buttonC_Click(sender As Object, e As EventArgs) Handles buttonC.Click
    Task.Delay(50 * 1000).ContinueWith(Sub() ProcessD())
End Sub

Private Sub ProcessD()
    MsgBox("処理Dを実行しました。")
End Sub