gpt4 book ai didi

.net - 用自定义异步计时器类替换 Threading.Timer?

转载 作者:行者123 更新时间:2023-12-02 01:45:44 25 4
gpt4 key购买 nike

我正在尝试用可以处理异步函数的代码替换旧的 Threading.Timer 代码。我这样做的原因是您不能将 Threading.Timer 传递给异步函数而不将其设为 Async Sub,我认为这是一个坏主意。

我想替换的代码;

Dim SaveTimer as New Threading.Timer(AddressOf SaveToFile, Nothing, 1000 * 60 * 5, 1000 * 60 * 5)

SaveToFile 是一个异步函数,因此我收到“从此异步函数返回的任务将被删除,并且忽略其中的任何异常。考虑将其更改为异步子函数以便传播其异常”警告。

这个计时器的目的是每 5 分钟将它所在的类的内容保存到一个文件中。但是,我偶尔也会手动调用 SaveToFile,如果我这样做了,我想重置计时器。

有了 Threading.Timer,我会这样做;

  Public Async Function ManuallySave As Tasks.Task
SaveTimer.Change(Timeout.Infinite, Timeout.Infinite)
Await SaveToFile
SaveTimer.Change(1000 * 60 * 5, 1000 * 60 * 5)
End Function

现在我知道如何使用 Task.Delay 安排要完成的任务,但我不确定如何停止和重置它。

这是我对异步计时器类的尝试;

Public Class AsyncTimer

Private CancellationToken As New CancellationTokenSource
Private DelegateAction As Action(Of Tasks.Task) = Nothing

Public Sub New(DelegateAction As Action(Of Tasks.Task))
Me.DelegateAction = DelegateAction
End Sub

Public Async Function StartTimer(Interval As Integer, Optional Repeat As Boolean = False) As Tasks.Task
CancellationToken = New CancellationTokenSource
Do
Await Tasks.Task.Delay(Interval, CancellationToken.Token).ContinueWith(DelegateAction, CancellationToken.Token, TaskContinuationOptions.NotOnCanceled, TaskScheduler.Current)
Loop Until Not Repeat OrElse CancellationToken.IsCancellationRequested
End Function

Public Sub StopTimer()
CancellationToken.Cancel()
End Sub

End Class

让我担心的是,我调用了 StopTimer,然后不久又调用了 StartTimer,它用一个新实例替换了 CancellationToken。我担心在取消 token 生效之前我会覆盖它。

解决这个问题的方法是什么?

我知道代码是用 VB 编写的,但我也理解 C#,所以作为答案都可以。

EDIT1:这需要是线程安全的。这是我担心的原因。

最佳答案

计时器滴答排队到线程池。您可以在那里使用 asyncawait 没有问题。让您的 tick 函数调用 async Task 函数并丢弃生成的任务。并记录为什么。

void TimerProc(...) {
var task = TimerImpl();
//throw away task
}

async Task TimerImpl() {
try { MyCode(); }
catch (Exception ex) { Log(ex); }
}

请注意,计时器滴答可以任意延迟,它们可以并发执行,并且可以在您停止计时器后运行。

我不明白你为什么需要使用异步代码。您已经在线程池中,因此您不必解除对 UI 的阻塞。写入本地磁盘不会从异步 IO 中获益太多。也许答案是:在这里使用同步代码即可。

为了防止覆盖CancellationToken,您需要将它复制到所有使用它的地方。任何东西都不应直接使用该字段。

更好的是,创建一个新的 AsyncTimer 实例,而不是让它可重启。避免状态突变。

关于.net - 用自定义异步计时器类替换 Threading.Timer?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25823696/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com