在Blazor中显示计时器 [英] Display a timer in Blazor

查看:273
本文介绍了在Blazor中显示计时器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在服务器端Blazor应用中显示倒数计时器.我的代码同时在F#和C#中.该代码有些起作用,但是计时器永远不会按预期停止,并且计时器显示偶尔也不会呈现所有数字.这是我第一次尝试使用Blazor服务器端应用程序.我不确定问题是异步问题,计时器问题还是渲染问题.

I am attempting to display a countdown timer in a server-side Blazor app. My code is in both F# and C#. The code somewhat works, but the timer never stops as intended, and the timer display sporadically does not render all of the numbers. This is my first attempt at a Blazor server-side app. I am not sure if the problem is an async issue, timer issue, or rendering issue.

这是我的代码:

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#/开拓者

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

}

推荐答案

rmunn使我步入正轨,但由于我不完全了解计时器类的实际功能,因此我的逻辑有些偏离.为了使所有内容保持同步,我不仅要考虑开始时间,还要考虑时间间隔,现在代码可以按预期工作了.这是更新的代码:

rmunn got me on the right track, but my logic was a bit off as I did not fully understand what the timer class was actually doing. I had to account for not only the start time but the interval as well to get everything in sync, and the code now works as intended. Here is the updated code:

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

C#/Blazor:

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

}

这篇关于在Blazor中显示计时器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆