C#:等待n毫秒,并且每n / m毫秒测试一个布尔值

时间:2017-06-07 14:46:35

标签: c# timer

我必须每250毫秒测试一个布尔值,最多2秒,并且当它为真时停止。
试过这个,但Thread.Sleep对我来说不是一个很好的解决方案,因为它冻结了我的软件,等待更多的东西不会改变任何东西,因为布尔不会改变#&# 39;冷冻。

bool onLine = false;
Stopwatch chrono = new Stopwatch();
chrono.Start();
while (chrono.ElapsedMilliseconds < 2000)
{
    if (!State().Equals(Online))
    {
        System.Threading.Thread.Sleep(250);
    }
    else
    {
        onLine = true;
        operationCompleted();
        break;
    }
}
if (!onLine)
{
    MessageBox.Show("Error");
}

如果某人有正确的实施,我不知道如何在计时器引发的事件中进行测试?

5 个答案:

答案 0 :(得分:3)

currently accepted answer并未特别善用async await范例,并为不必复杂的事情引入了大量噪音。简单地使用Task.Run将同步,阻塞代码安排到ThreadPool上而不是升级到完全异步代码是一个半措施。

重写没有阻止代码和虚假Task.Run的代码,它可以简单如下:

private async void button1_Click(object sender, EventArgs e)
{
    bool onLine = false;
    Stopwatch chrono = new Stopwatch();
    chrono.Start();
    while (chrono.ElapsedMilliseconds < 2000)
    {
        if (!State().Equals(Online))
        {
            await Task.Delay(250);
        }
        else
        {
            onLine = true;
            break;
        }
    }

    if (onLine)
    {
        operationCompleted();
    }
    else
    {
        MessageBox.Show("Error");
    }
}

答案 1 :(得分:1)

不确定它在WPF中的样子,但是这里是如何在WinForms中完成的。请注意,按钮处理程序已标记为__init__.py

async

答案 2 :(得分:1)

以下是使用线程计时器的示例:

public class Foo
{
    public System.Threading.Timer EventTimer
    {
        get;
        set;
    }

    public long TimingInterval
    {
        get;
        set;
    }
    public Foo()
    {
        EventTimer = new System.Threading.Timer(new TimerCallback(Foo.DoCheck),
            this,
            this.TimingInterval,
            this.TimingInterval);
    }
    public void DoCheck()
    {
        //do check here
    }

答案 3 :(得分:1)

这是使用计时器实现的一种方法。我们的想法是将间隔设置为您要检查的频率,并将超时变量设置为您要停止检查的时间。然后,在Tick事件(触发每个间隔)中,进行在线检查,然后检查超时。

[更新了WPF以使用DispatcherTimer]

System.Windows.Threading.DispatcherTimer timer = new DispatcherTimer(); 
private DateTime timeout;

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    timeout = DateTime.Now.AddSeconds(2);
    timer.Tick += Timer_Tick;
    timer.Interval = TimeSpan.FromMilliseconds(250);
    timer.Start();
}

private void Timer_Tick(object sender, EventArgs e)
{
    if (State().Equals(Online))
    {
        onLine = true;
        operationCompleted();
        timer.Stop();
    }

    if (DateTime.Now > timeout)
    {
        timer.Stop();
        MessageBox.Show("Error");
    }
}

// rest of code omitted

答案 4 :(得分:0)

您可以使用BackgroundWorker

BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += bw_DoWork;
bw.RunWorkerCompleted += bw_RunWorkerCompleted;

DoWork的{​​{1}}事件处理程序在deditecated线程上执行,因此您的软件不会冻结。

BackgroundWorker

后台操作完成后,会发生private void bw_DoWork(object sender, DoWorkEventArgs e) { bool onLine = false; Stopwatch chrono = new Stopwatch(); chrono.Start(); while (chrono.ElapsedMilliseconds < 2000) { if (!State().Equals(Online)) { System.Threading.Thread.Sleep(250); } else { onLine = true; break; } } e.Result = onLine; } 事件。您可以使用,将对象从RunWorkerCompleted传递到DoWork RunWorkerCompleted

e.Result

enter image description here

调用private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { bool onLine = (bool)e.Result; if (onLine) { operationCompleted(); } else { MessageBox.Show("Error"); } } 时出现

DoWork。您必须致电RunWorkerAsync以启动bw.RunWorkerAsync();