[c#] 新しいスレッドで簡単なコードを実行するにはどうすればよいですか?



6 Answers

BackgroundWorkerがあなたにとって最良の選択であるようです。

ここに私の最小の例があります。 ボタンをクリックすると、バックグラウンドワーカーはバックグラウンドスレッドで作業を開始し、同時に進行状況を報告します。 また、作業が完了した後に報告されます。

using System.ComponentModel;
...
    private void button1_Click(object sender, EventArgs e)
    {
        BackgroundWorker bw = new BackgroundWorker();

        // this allows our worker to report progress during work
        bw.WorkerReportsProgress = true;

        // what to do in the background thread
        bw.DoWork += new DoWorkEventHandler(
        delegate(object o, DoWorkEventArgs args)
        {
            BackgroundWorker b = o as BackgroundWorker;

            // do some simple processing for 10 seconds
            for (int i = 1; i <= 10; i++)
            {
                // report the progress in percent
                b.ReportProgress(i * 10);
                Thread.Sleep(1000);
            }

        });

        // what to do when progress changed (update the progress bar for example)
        bw.ProgressChanged += new ProgressChangedEventHandler(
        delegate(object o, ProgressChangedEventArgs args)
        {
            label1.Text = string.Format("{0}% Completed", args.ProgressPercentage);
        });

        // what to do when worker completes its task (notify the user)
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
        delegate(object o, RunWorkerCompletedEventArgs args)
        {
            label1.Text = "Finished!";
        });

        bw.RunWorkerAsync();
    }

注意:

  • 単純化のためにC#の匿名メソッドを使ってすべてを単一のメソッドに入れますが、あなたはいつもそれらを別のメソッドに引き出すことができます。
  • ProgressChangedまたはRunWorkerCompletedハンドラ内でGUIを更新することは安全です。 ただし、 DoWorkからGUIを更新すると、 InvalidOperationExceptionが発生しInvalidOperationException
Question

現在、コードが実行中(10秒程度)にフォームがフリーズするため、GUIとは別のスレッドで実行する必要があるコードがあります。

前に新しいスレッドを作成したことがないと仮定します。 C#でこれを行い、.NET Framework 2.0以降を使用する方法の簡単な/基本的な例は何ですか?




BackgroundWorkerクラスを使用してみてください。 あなたは何を実行するのかを委任し、作業が終わったら通知を出します。 私がリンクしているMSDNページの例があります。




Jeff RichterのPower Threading Library 、特にIAsyncEnumeratorを見てみることをお勧めします。 Richter氏がその概要を説明しているCharlie Calvertのブログのビデオを見てください。

非同期プログラミングタスクのコード作成が容易になるため、名前を付けないでください。




そのコードを関数(GUIと同じスレッド上で実行できないコード)に入れ、そのコードの実行をトリガーするには、次のように記述します。

Thread myThread= new Thread(nameOfFunction);

workerThread.Start();

スレッドオブジェクトでstart関数を呼び出すと、新しいスレッドで関数呼び出しが実行されます。




クイックと汚れ、しかしそれは動作します:

上から:

using System.Threading;

簡単なコード:

static void Main( string[] args )
{
    Thread t = new Thread( NewThread );
    t.Start();
}

static void NewThread()
{
    //code goes here
}

私はこれを新しいコンソールアプリケーションに投げて




// following declaration of delegate ,,,
public delegate long GetEnergyUsageDelegate(DateTime lastRunTime, 
                                            DateTime procDateTime);

// following inside of some client method 

    GetEnergyUsageDelegate nrgDel = GetEnergyUsage;                     
    IAsyncResult aR = nrgDel.BeginInvoke(lastRunTime, procDT, null, null);
    while (!aR.IsCompleted) Thread.Sleep(500);
    int usageCnt = nrgDel.EndInvoke(aR);

チャールズあなたのコード(上記)は正しくありません。 あなたは完了を待つ必要はありません。 WaitHandleが通知されるまで、EndInvokeはブロックされます。

完了までブロックする場合は、

nrgDel.EndInvoke(nrgDel.BeginInvoke(lastRuntime,procDT,null,null));

あるいは

ar.AsyncWaitHandle.WaitOne();

しかし、あなたがブロックすれば、anyc呼び出しを発行するポイントは何ですか? 同期呼び出しを使用することもできます。 より良い賭けは、クリーンアップのためにラムダをブロックして渡すことではありません:

nrgDel.BeginInvoke(lastRuntime,procDT,(ar)=> {ar.EndInvoke(ar);},null);

あなた EndInvokeを呼び出さなければならないことを覚えておいてください。 多くの人々がこれを忘れて、ほとんどの非同期実装がEndInvokeでwaithandleを解放するので、WaitHandleを漏らしてしまいます。




デリゲートとスレッドプールを使用する別のオプション...

'GetEnergyUsage'が入力引数としてDateTimeと別のDateTimeを受け取り、Intを返すメソッドであると仮定します。

// following declaration of delegate ,,,
public delegate long GetEnergyUsageDelegate(DateTime lastRunTime, 
                                            DateTime procDateTime);

// following inside of some client method 
GetEnergyUsageDelegate nrgDel = GetEnergyUsage;                     
IAsyncResult aR = nrgDel.BeginInvoke(lastRunTime, procDT, null, null);
while (!aR.IsCompleted) Thread.Sleep(500);
int usageCnt = nrgDel.EndInvoke(aR);



Related