0

Windows フォーム C# で Thread.Sleep を使用しています。これを使用すると、フォームが応答しません。タイマーの使用も私の目的には役立っていません。

サンプルコード:

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 形式の代替案を教えてください。コマンド間に特定の一時停止が必要です。

4

3 に答える 3

13

最も簡単なオプションは、次のモデルを使用することです。

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 でa を再作成することは可能Taskですが (4.0 の言語機能を利用していません)、それを行う既存のライブラリがありますが、これは多少複雑になります。

于 2013-05-29T16:39:43.737 に答える
1

上記のコードをバックグラウンド スレッドに配置すると、UI スレッドがブロックされなくなります。待機中のメソッドが UI アクセスを必要とすると仮定すると、Control.BeginInvoke を使用して UI スレッドを更新できます。

于 2013-05-29T16:41:55.190 に答える
0

BackgroundWorkerを検討する必要があります。

現在、.NET Framework 4.5 のみが async-await メカニズムをサポートしています。

下位互換性のあるソリューションを検討している場合は、CodeProject のこのリンクを確認してください。

バックグラウンド ワーカーは、実行時間の長いプロセスのために別のスレッド コンテキストでタスクを非同期的に実行し、UI の応答性を維持します。

それが役に立てば幸い

于 2013-05-29T16:44:01.200 に答える