我正在尝试在服务器端 Blazor 应用程序中显示倒计时器。我的代码同时使用 F# 和 C# 语言。该代码在某种程度上可以工作,但计时器永远不会按预期停止,并且计时器显示偶尔不会呈现所有数字。这是我第一次尝试 Blazor 服务器端应用程序。我不确定问题是异步问题、计时器问题还是渲染问题。
这是我的代码:
F#
let private setTimer countDown timeEvent =
let timer = new Timer(float countDown * float 1000)
let mutable time = 0
time <- countDown
timer.Elapsed.Add(fun arg ->
time <- time - 1
if time = 0
then
timer.Stop()
timer.Dispose()
else
()
timeEvent arg
)
timer.AutoReset <- true
timer.Start()
let setTimerAsync countDown timeEvent = async{
setTimer countDown timeEvent
do! Async.Sleep (countDown * 1000)
}
type Timer (countDown) =
member val CountDown : int = countDown with get,set
member this.SetTimeAsTask (timeEvent) =
setTimerAsync countDown timeEvent |> Async.StartAsTask
C#/Blazor
@page "/CountDown"
@using System.Timers
@using ClientTImer
@using Microsoft.FSharp.Core
<h3>Count Down</h3>
<p>
Task: @task <br />
Status: @status
</p>
<p>
Timer: @time
</p>
@code {
string task = "";
string status = "";
int time = 5;
protected override async Task OnInitializedAsync()
{
// Initial task and status
task = "First Task";
status = "Status One";
Action<System.Timers.ElapsedEventArgs> timeEvent =
t =>
{
UpdateTime().Wait();
};
var func = FuncConvert.ToFSharpFunc(timeEvent);
await new ClientTImer.Timer(time).SetTimeAsTask(func);
// Update task and status
task = "Second Task";
status = "Status Two";
await new ClientTImer.Timer(time).SetTimeAsTask(func);
// Update task and status
task = "Third Task";
status = "Status Three";
}
public async Task UpdateTime()
{
await InvokeAsync(() =>
{
time--;
StateHasChanged();
});
}
}
在你的 F# 里面Timer.Elapsed
事件处理程序,你的最后一行是timeEvent
(没有参数),我从你的代码的其余部分看到timeEvent
is an Action
已转换为 F# 函数。由于你之后没有写任何参数timeEvent
,该行的作用是指定value of timeEvent
作为事件处理程序的返回值,即您的事件处理程序正在返回一个函数。或者它would如果事件处理程序返回除以下内容之外的其他内容,则返回一个函数void
(or unit
以 F# 术语表示)。因为他们没有,我怀疑你已经收到了警告timeEvent
说明了以下内容的值的行timeEvent
本质上被忽视。
另外,你的timer.Elapsed.Add
F# 中的行对我来说看起来不对。这Add
事件方法采用类型参数'T -> unit
, where 'T
是事件为您提供的任何类型的数据:Elapsed
定时器上的事件,那将是ElapsedEventArgs
实例。你应该传递给什么Add
is a fun elapsedEventArgs -> ...
。然后你会改变你的timeEvent
行实际传递一个参数(那些相同的elapsedEventArgs
)以便它被调用并实际执行某些操作。
另外,每当你递减一个数字并将其与 0 进行比较时,我总是喜欢进行比较<=
而不是=
,只是万一我稍后更改代码可能会导致递减发生两次。如果我的比较是= 0
双减法将数字从 1 减到 -1,if x = 0
分支不会触发。但如果我比较<= 0
,那么即使我在其他地方犯了错误,它也会触发。所以我建议写if time <= 0
而不是if time = 0
.
换句话说,我认为你的timer.Elapsed
事件处理程序需要如下所示:
timer.Elapsed.Add(fun evtArgs ->
time <- time - 1
if time <= 0
then
timer.Stop()
timer.Dispose()
else
()
timeEvent evtArgs
)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)