1

そのため、「ボタン 2」を押してみると、2 つのことが起こると予想されます。b)何かをしている間、何かにかかる時間を数えたい。ただし、「dosomething」はプログラムに飢えているため、Form1 がフリーズし、タイマーが実行されません。私はC#の新人なので、バックグラウンドで実行する方法がわかりません。では、既成概念にとらわれないアイデアはありますか? ありがとう。

     int time = 0;
    private void button2_Click(object sender, EventArgs e)
    {
            timer1.Start();
            nowthen now = new nowthen();
            now.dosomething(withthis); //This task is program hungry and causes the form to freeze
            timer1.Stop();
            time = 0;  
    }
    private void timer1_Tick(object sender, EventArgs e)
    {
        time = time + 1;
        label2.Text = time.ToString();
        label2.Refresh();
    }
4

4 に答える 4

3

Windows フォームでは、すべての UI が 1 つのスレッドで実行されます。これにはタイマーが含まれます。タイマーは、Windows メッセージを使用して舞台裏で実装されます。

あなたの質問は実際には2つの質問です:-

  1. C#/Windows フォームで操作の時間を計るにはどうすればよいですか?

何かを計る方法は、探している精度によって異なります。+/- 10ms の精度を得るには、Environment.TickCount を使用できます。操作前に値を保存し、操作後に値を再度取得し、保存された値を減算します。

より正確には、System.Threading の Stopwatch クラスです。http://www.dotnetperls.com/stopwatchを参照してください。

  1. 「バックグラウンドで」タスクを実行するにはどうすればよいですか?

操作をバックグラウンドで実行するには、別のスレッドで実行する必要があります。最も簡単でフレンドリーに設計された (ただし、それほど柔軟な方法ではないかもしれません) 方法は、BackgroundWorker コンポーネントを使用することです。これは、ワーカー スレッドを使用してラップし、操作を実行します。その方法の詳しい説明については、http://www.dotnetperls.com/backgroundworkerを参照してください。

より高度で柔軟なのは、独自のスレッドを作成して作業を行うことです。ただし、これにより、何が起こっているかを同期する方法について考慮すべきいくつかの重要な問題が発生します。スレッドを開始するとすぐに、メソッド呼び出しが終了し (非同期です)、プロセスにあることを UI コードに通知するメカニズムが必要です。終了した。この例は、独自のスレッドを作成する方法と同じくらい良いようです: http://www.daveoncsharp.com/2009/09/create-a-worker-thread-for-your-windows-form-in-csharp/

于 2013-03-15T16:47:00.157 に答える
2

何かにかかる時間を計りたいだけなら、System.Diagnostics.Stopwatchを使用してください。

Stopwatch sw = Stopwatch.StartNew();
nowThen = new nowThen();
no.dosomething(withthis);
sw.Stop();
// you can get the time it took from sw.Elapsed

ただし、ラベルは経過時間で更新されません。

于 2013-03-15T16:45:31.357 に答える
2

.NET 4 の場合:

Task.Factory.StartNew((Action) delegate()
{
    // this code is now executing on a new thread.
    nowthen now = new nowthen();
    now.dosomething(withthis);

    // to update the UI from here, you must use Invoke to make the call on UI thread
    textBox1.Invoke((Action) delegate()
    {
          textBox1.Text = "This update occurs on the UI thread";
    });
});
于 2013-03-15T16:42:05.603 に答える
1

@paulのソリューションほどエレガントではありませんが、私もこれを投入すると思います。

timer1.Start();
var bw = new BackgroundWorker();
bw.DoWork += (s, e) => { now.dosomething((myArgumentType)e.Argument); };
bw.RunWorkerCompleted += (s, e) => { timer1.Stop(); };
bw.RunWorkerAsync(withthis);

これにより、タイマーが開始され、新しいBackgroundWorkerスレッドが作成され、メソッドで何を実行するかが指示されDoWork(何かが別のスレッドで実行されます)、RunWorkerCompletedメソッドでタイマーが停止します(何かが終了すると、制御はRunWorkerCompletedのメインスレッドに戻ります) 。

于 2013-03-15T17:03:44.300 に答える