use*_*480 6 c# asp.net f# blazor-server-side asp.net-core-3.0
我正在尝试在服务器端 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
Run Code Online (Sandbox Code Playgroud)
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();
});
}
}
Run Code Online (Sandbox Code Playgroud)
rmunn 让我走上了正轨,但我的逻辑有点偏离,因为我没有完全理解计时器类实际上在做什么。我不仅必须考虑开始时间,还必须考虑间隔,以使所有内容同步,并且代码现在按预期工作。这是更新后的代码:
F#:
let private setTimer countDownSec intervalSec timeEvent =
let timer = new Timer(float intervalSec * float 1000)
let mutable time = 0
time <- countDownSec
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 internal setTimerAsync countDownSec intervalSec timeEvent = async{
setTimer countDownSec intervalSec timeEvent
do! Async.Sleep (countDownSec * 1000)
}
type Timer (countDown) =
member val CountDown : int = countDown with get,set
member this.SetTimeAsTask (timeEvent, interval) =
setTimerAsync countDown interval timeEvent |> Async.StartAsTask
Run Code Online (Sandbox Code Playgroud)
C#/Blazor:
@page "/CountDown"
@using System.Timers
@using ClientTImer
@using Microsoft.FSharp.Core
@using System.Threading
<h3>Count Down</h3>
<p>
Task: @task <br />
Status: @status
</p>
<p>
Timer: @time
</p>
@code {
string task = "";
string status = "";
int startCount = 5;
int time;
protected override async Task OnInitializedAsync()
{
time = startCount;
// 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(startCount).SetTimeAsTask(func,1);
// Update task and status
task = "Second Task";
status = "Status Two";
await new ClientTImer.Timer(startCount).SetTimeAsTask(func,1);
// Update task and status
task = "Third Task";
status = "Status Three";
}
public async Task UpdateTime()
{
await InvokeAsync(() =>
{
time--;
if(time <= 0)
{
time = startCount;
}
StateHasChanged();
});
}
}
Run Code Online (Sandbox Code Playgroud)