【问题标题】:How can I pause an execution without using Thread.Sleep() [duplicate]如何在不使用 Thread.Sleep() 的情况下暂停执行 [重复]
【发布时间】:2019-05-09 09:37:25
【问题描述】:

例如,我有几行代码:

MessageBox.Show("1");

Sleep(1000);

MessageBox.Show("2");

Sleep(1000);

MessageBox.Show("3");

我想在不使用Thread.Sleep 的情况下继续下一个代码行之前暂停 1 秒;因为它冻结了整个表单并终止了应该在睡眠代码之前执行的代码行。我不为此使用消息框,我仅用作示例,我知道它适用于这些。

对于我最初使用的行,它不起作用。在继续运行代码之前是否有其他替代方法可以等待 1 秒?谢谢。

【问题讨论】:

  • 是的,让你的方法异步并使用await Task.Delay(1000)
  • “还有其他选择吗” - 很多。 async/await 可能是最好的。如果您可以将操作拆分为多个步骤,那么Timer 可以做到。如果您想避免 UI 冻结,请研究多线程:TaskThreadBackgroundWorker 等。
  • 您应该提供更多信息。请张贴您的方法的签名,并告诉我们您正在使用哪种 UI 技术。 WPF、WinForms 等...

标签: c# winforms wait


【解决方案1】:

是的,让你的方法异步并使用 await Task.Delay(1000)

public async Task MyAsyncMethod()
{
    //Action 1  
    await Task.Delay(1000);

    //Action 2  
    await Task.Delay(1000);


    //Action 3  
    await Task.Delay(1000);
}

编辑:

如果使用 Winforms,这种异步模式必须转到层次结构中的最高层方法。因此,假设您确实有一个要调用此方法的按钮单击事件。然后你必须使点击方法异步!

private async void button2_Click(object sender, EventArgs e)
{
    Console.WriteLine("STUFF Before");
    await MyAsyncMethod();
    Console.WriteLine("STUFF @ the END");
}

public async Task MyAsyncMethod()
{
    //Action 1  
    Console.WriteLine("Action 1 ");
    await Task.Delay(1000);

    //Action 2  
    Console.WriteLine("Action 2 ");
    await Task.Delay(1000);


    //Action 3  
    Console.WriteLine("Action 3 ");
    await Task.Delay(1000);
}

要实现这一点,您需要将MyAsyncMethod 的返回类型声明为Task

public async Task MyAsyncMethod()    
               ^
               !

【讨论】:

  • 不需要在Dispatcher中完成?
  • 这对我不起作用。我正在创建此方法,然后在我想等待 3 秒时调用它。我做错了吗?
  • @GucciHoodie - 也许但是很难判断您是否不发布您现在正在运行的代码。使用您正在使用的新代码更新您的问题。
  • @GucciHoodie 请按照我在上面评论中提到的方法发布您的方法
  • @GucciHoodie 我做了一个例子,如何在 Winforms 中使用它来工作
【解决方案2】:

编辑:

在响应中做出cmets后,最好的解决方案是使用await Task.Delay(time);

private async void AsyncMethod()
{
    //do what you want here
    await Task.Delay(1000);
}

这种方式是一种不好的做法,就像@MickyD 在他的评论中所说:

它会导致您的 GUI 应用程序成为可重入的。这是对 Visual Basic 6 和不良编码实践的回归。

int seconds = 2;
if (seconds < 1) return;
DateTime _desired = DateTime.Now.AddSeconds(seconds);
while (DateTime.Now < _desired)
{
   System.Windows.Forms.Application.DoEvents();
   //do whatever you want in this 2 seconds
}

【讨论】:

  • 老兄,非常感谢!我一直在寻找几个小时,但没有任何效果,我还没有看到任何替代代码。我将您的代码粘贴到一个方法中,并在 () 中创建了一个 var,所以每次我想暂停时,我只使用 waitSec(4);它等待 () 内的秒数;太棒了!
  • 永远永远永远永远永远永远永远永远使用Application.DoEvents!。它会导致您的 GUI 应用程序变得可重入。这是对 Visual Basic 6 和不良编码实践的回归。 Mong's answer 是要走的路
  • @MickyD Application.DoEvents 和 Async Task.Delay 的主要区别是什么?
  • Application.DoEvents() 拥有自己的 Windows 消息泵处理功能,可以处理鼠标点击和键盘等操作。问题是,当您决定调用DoEvents()时,大多数时候您已经在事件处理程序中,但您还没有从事件处理程序返回。现在有可能在第一个事件完成之前从菜单/工具栏处理另一个事件。这将导致意外的应用程序状态。效果类似于将多线程应用于非线程安全的代码
猜你喜欢
  • 2021-11-25
  • 2016-09-21
  • 1970-01-01
  • 2017-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-21
  • 2022-12-10
相关资源
最近更新 更多