簡體   English   中英

Windows形式中的Thread.Sleep的替代品,計時器除外

[英]Alternative to Thread.Sleep in windows Form apart from Timer

我在Windows窗體C#中使用Thread.Sleep。 使用它會導致表單不響應。 使用Timer也不符合我的目的。

樣例代碼:

if(......)    // There are many if with difrent components and many Thread.sleep
{
      button.visible=true;
      Thread.sleep(1000);
      GotoMeasurementMode(3000);
      Thread.sleep(3000);
      query(device.Text);
      Thread.sleep(7000);
      StopMeasurement();
      Thread.sleep(4000);
 }

使用上述代碼會導致表單無響應。 使用計時器會導致嵌套計時器。 而就我而言,這並不令人滿意。 請告訴我Windows形式的替代方法。 想要命令之間的特定暫停。

最簡單的選擇是使用以下模型:

public async void button1_Click(object sender, EventArgs args)
{
    if(condition)
    {
        button.visible=true;
        await Task.Delay(1000);
        GotoMeasurementMode(3000);
        await Task.Delay(3000);
        query(device.Text);
        await Task.Delay(7000);
        StopMeasurement();
        await Task.Delay(4000);
    }
}

如果您無權訪問C#5.0,則可以在4.0中執行此操作。 您需要從自己的Delay方法開始,因為.NET 4.0中不存在該方法:

public static Task Delay(int milliseconds)
{
    var tcs = new TaskCompletionSource<bool>();
    var timer = new System.Threading.Timer(o => tcs.SetResult(false));
    timer.Change(milliseconds, -1);
    return tcs.Task;
}

使用它,我們現在可以編寫:

Delay(1000)
    .ContinueWith(t => GotoMeasurementMode(3000), TaskScheduler.FromCurrentSynchronizationContext())
    .ContinueWith(t => Delay(3000)).Unwrap()
    .ContinueWith(t => query(device.Text), TaskScheduler.FromCurrentSynchronizationContext())
    .ContinueWith(t => Delay(7000)).Unwrap()
    .ContinueWith(t => StopMeasurement(), TaskScheduler.FromCurrentSynchronizationContext())
    .ContinueWith(t => Delay(4000)).Unwrap();

這與第一個代碼片段將被編譯到的代碼非常相似,但是顯然第一個代碼片段要漂亮得多,因此,請盡可能使用它。

如果返回C#3.0,則將失去對Task訪問權限,這意味着我們將返回使用計時器和回調。 我們將從這個簡單的輔助方法開始,為我們處理任務管理:

public static void ExecuteIn(int milliseconds, Action action)
{
    var timer = new System.Windows.Forms.Timer();
    timer.Tick += (s, e) => { action(); timer.Stop(); };
    timer.Interval = milliseconds;
    timer.Start();
}

然后我們可以嵌套對此的調用:

ExecuteIn(1000, () =>
{
    GotoMeasurementMode(3000);
    ExecuteIn(3000, () =>
    {
        query(device.Text);
        ExecuteIn(7000, () => StopMeasurement());
    });
});

盡管可以在C#3.0中重新創建Task (它不利用4.0語言功能中的任何一種),並且現有的庫都可以這樣做,但要花更多的精力。

將上面的代碼放在后台線程中,這樣就不會阻塞UI線程。 假設兩次等待之間的方法需要UI訪問,則它們可以使用Control.BeginInvoke在UI線程上進行更新。

您應該考慮使用BackgroundWorker

當前,只有.NET Framework 4.5支持異步等待機制。

如果您正在尋找向后兼容的解決方案,則應在CodeProject上查看此鏈接。

后台工作人員將在單獨的線程上下文中異步執行您的任務以延長流程的運行時間,從而保持用戶界面的響應速度,

希望能幫助到你

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM