c#-等待几秒钟而不会阻止UI执行

我想在两条指令之间等待几秒钟,但不会阻塞执行。

例如2702263973604604492288,它不好,因为它阻止了执行。

我的想法是先调用一个方法,然后等待X秒(例如20秒)来监听事件的到来。 在20秒结束时,我应该根据20秒中发生的事情进行一些操作。

user3376691 asked 2020-01-14T12:33:18Z
7个解决方案
82 votes

我认为您所追求的是Task.Delay。 这不会像Sleep那样阻塞线程,这意味着您可以使用异步编程模型使用单个线程来执行此操作。

async Task PutTaskDelay()
{
    await Task.Delay(5000);
} 

private async void btnTaskDelay_Click(object sender, EventArgs e)
{
    await PutTaskDelay();
    MessageBox.Show("I am back");
}
daniellepelley answered 2020-01-14T12:33:47Z
24 votes

我用:

private void WaitNSeconds(int segundos)
{
    if (segundos < 1) return;
    DateTime _desired = DateTime.Now.AddSeconds(segundos);
    while (DateTime.Now < _desired) {
         System.Windows.Forms.Application.DoEvents();
    }
}
Omar answered 2020-01-14T12:34:07Z
12 votes

这是使用另一个线程的好例子:

// Call some method
this.Method();

Task.Factory.StartNew(() =>
{
    Thread.Sleep(20000);

    // Do things here.
    // NOTE: You may need to invoke this to your main thread depending on what you're doing
});

上面的代码要求使用.NET 4.0或更高版本,否则请尝试:

ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
{
    Thread.Sleep(20000);

    // Do things here
}));
Matt answered 2020-01-14T12:34:31Z
10 votes

如果您无法将环境升级到.NET 4.5以获得对异步和等待API的访问权限,则Omar的解决方案是不错的*。 也就是说,这里应该进行一项重要的更改,以避免性能下降。 在两次调用Application.DoEvents()之间应添加一些延迟,以防止CPU使用率过高。 通过添加

Thread.Sleep(1);

在调用Application.DoEvents()之前,您可以添加这样的延迟(1毫秒),并阻止应用程序使用所有可用的CPU周期。

private void WaitNSeconds(int seconds)
{
    if (seconds < 1) return;
    DateTime _desired = DateTime.Now.AddSeconds(seconds);
    while (DateTime.Now < _desired) {
         Thread.Sleep(1);
         System.Windows.Forms.Application.DoEvents();
    }
}

*有关使用Application.DoEvents()的潜在陷阱的详细讨论,请参见[https://blog.codinghorror.com/is-doevents-evil/]。

Nick Painter answered 2020-01-14T12:35:01Z
3 votes

如果您不想阻塞事物,也不想使用多线程,则可以使用以下解决方案:[https://msdn.microsoft.com/zh-CN/library/system.timers.timer(v=vs.110).aspx]

UI线程未被阻止,计时器等待2秒钟后再执行操作。

这是来自上面链接的代码:

        // Create a timer with a two second interval.
    aTimer = new System.Timers.Timer(2000);
    // Hook up the Elapsed event for the timer. 
    aTimer.Elapsed += OnTimedEvent;
    aTimer.Enabled = true;

    Console.WriteLine("Press the Enter key to exit the program... ");
    Console.ReadLine();
    Console.WriteLine("Terminating the application...");
Daan answered 2020-01-14T12:35:30Z
2 votes

我真的不建议您使用Thread.Sleep(),因为几个原因(这里描述了几个原因),但最主要的原因是它在调试/测试时没有用。

我建议使用C#计时器而不是Thread.Sleep()。计时器使您可以频繁地执行方法(如有必要),并且在测试中更容易使用! 有一个非常好的示例,说明如何在超链接后面使用计时器-只需将您的逻辑“ 2秒后会发生什么”直接放入Timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);方法中即可。

Matthias R. answered 2020-01-14T12:35:55Z
0 votes

查看System.Threading.Timer类。 我认为这就是您要寻找的。

MSDN上的代码示例似乎显示此类与您尝试执行的操作非常相似(在一定时间后检查状态)。

LB2 answered 2020-01-14T12:36:20Z
translate from https://stackoverflow.com:/questions/22158278/wait-some-seconds-without-blocking-ui-execution