2012-03-01 22 views
-2

私は2つのスレッドが同時にクラスからメソッドを実行するアプリケーションに取り組んでいます。このメソッドは複雑な計算を実行し、結果はWinFormに表示されます。C#はどのようにスレッドの切り替えを処理しますか?

だから私のクラスには、次のようになります。

class Comp_func 
{ 
    /* Constructor */ 
    public Comp_func() 
    { 
    } 

    public void THE_Complex_func(string One, Int16 Two, Int32 Three) 
    { 
     Calculate_this(One); 
     Thread.Sleep(10); 
     Calculate_that(Two); 
     Thread.Sleep(10); 
     Calculate_thatThat(Three); 
     Thread.Sleep(10); 
     Update_lable_in_form(value); 
     Thread.Sleep(10); 
    } 
} 

各スレッドがそうのWinFormに異なるLabelを更新し、私は(私はスレッドセーフメソッドを使用していたとして)スレッドの同期については問題を期待していません。

私の必要性は、それらの更新が同時に発生する必要があります(少なくとも同時に発生するようです)。

私の形で、「計算」ボタンをユーザーがクリックすると、私が行うと:

Comp_func Func1_class = new Comp_func(); 
Comp_func Func2_class = new Comp_func(); 

Thread Func1_Thread = new Thread(() => Func1_class.Start_Test("Blah", 2,3)); 
Thread Func2_Thread = new Thread(() => Func2_class.Start_Test("BlahBlah", 4,5)); 

//Func1_Thread.Priority = ThreadPriority.Highest; /* Deleted after Comments */ 
    // Func2_Thread.Priority = ThreadPriority.Highest; /* Deleted after Comments */ 


Func1_Thread.Start(); 
Func2_Thread.Start(); 

/* 
    // Removed after Comments 

// Let only Threads Run 
while(true) 
{ 
    Application.DoEvent(); 
    Update(); 
} 

for(count = 0; count < 100; count++) 
{ 
    console.WriteLine("I WON'T USE WHILE(1) loops with DOEVENTS"); 
} 

*/ 

私の問題は、スレッド1が完了の実行は、それがLabelを更新したときに、その後2つの開始を通し、ということです実行します。

この現象を回避するため、ほぼ各行の後にThread.Sleep();と書きました。あたかもウィンドウが切り替わっていないかのように振る舞います!

これはなぜ起こっているのですか?

ありがとうございました!

+1

あなたは何が起こることを期待していますか?通常、悪い習慣とみなされるいくつかの事柄についてのサイドノート。スレッド優先度、無限ループを明示的に示します。なぜあなたはThread.Sleep行が必要ですか? – kaj

+0

問題はスレッドが正しく切り替わらないことです。実行はスレッド1が完了してからスレッド2のようになります。だから私は、Thread.Sleepがスレッドを強制的に切り替えると考えました。 – Swanand

+1

スレッドが切り替わらないことをどのように知っていますか?あなたの関数呼び出しでは、各スレッドが一度だけ作業を完了したときに一度だけUIを更新します。あなたがスレッド1を持っているコードでは、スレッド2の前に常に完了します。 – dice

答えて

4

コード例は非常に不完全であるため、何が起こっているのかを確認するのは難しいです。あなたはあなたの条件2つのラベルの更新に応じて、すべての

while(true)..DoEvent()コードを必要はありません実際には - 私が持っているでしょう

最初のコメントは、あなたのクリックハンドラで無限ループを持つべきではないということです同時に、UIを更新する前にスレッドを結合させることをお勧めします。これを行う方法の1つは、他の2つのスレッドをJoin()してBackgroundWorkerを作成し、その結果をUIに更新します実行している.netのバージョンによっては、Tasksライブラリを使用してコードを少なくすることができます。 @diceにより示唆されるように

private void button1_Click(object sender, System.EventArgs e) 
    { 
     BackgroundWorker master= new BackgroundWorker(); 
     master.DoWork += (sender1, e1) => 
           { 
            Thread t1 = new Thread(Func1_class.Start_Test); 
            Thread t2 = new Thread(Func1_class.Start_Test); 
            t1.Start(); 
            t2.Start(); 
            t1.Join(); 
            t2.Join(); 
           }; 
     master.RunWorkerCompleted += (sender2, e2) => 
              { 
               label1.Text = "text"; 
               label2.Text = "text"; 
              }; 
     master.RunWorkerAsync(); 
    } 
+0

恐ろしい 'DoEvents'ループを解読するための+1。 –

+0

これは私があなたに条件を説明するために書いたテストコードの一種です。そして、私はDoEvent()とUpdate()を書いたので、いくつかのタイマ関数とスレッドを使ってフォームを更新したいと思っています:( – Swanand

+0

'プロセスいくつかのタイマ関数' - Windows.Forms.Timersは、 。 'フォームからスレッドを更新する'(Invoke/BeginInvokeを使用)は、OnClickハンドラを終了するだけでうまくいきます。 –

2

は()の呼び出しとDoEvents関数()ループ、睡眠を取り除く:ここ

は(使用可能なタスクのライブラリを持っていない場合)ではなく、粗実装です彼らはどれほどあなたがそうであっても、彼らは助けていません。正しくInvoke/BeginInvokeingを行っている場合は、ラベルの変更が必要です。OnClickイベントハンドラを終了するだけです。 GUIイベントハンドラーで待つべきではありません。

繰り返し - GUIイベントハンドラで待機しないでください。

あなたにはいくつのプロセッサコアがありますか、なぜワークスレッドの優先度を上げましたか? CPUが1つしかなく、Func1_ThreadでCPU集約型タスクを開始すると、100%CPUを使用して自身を停止するか、Windowsの飢餓防止アルゴリズムによって30秒後に他のスレッドに数サイクルが実行されます。これはシリアル化の印象を与えるでしょう。

スレッドを優先順位を上げてからsleep()呼び出しを挿入するだけです...まあ、やってはいけません!

+0

提案をお寄せいただきありがとうございます....これを覚えていますが、切り替えのためにThread.Sleepが挿入されました...私はスリープして1つのスレッドが別のものを目覚めさせると思った....優先順位は試用だった...そしてデュアルコア3GHzマシンで走る! – Swanand

1

実際にスレッドについて理解できないことがあります。

OSがどのようにスレッドの実行を処理するかを知る方法がありません。 ラベルを同時に変更したい場合は、自分で行う必要があります。

たとえば、スーパー関数の終わりにイベントを発生させるには、例としてSuperCalcDoneを呼び出します。 SuperCalcDoneハンドラでは、すべての計算が完了しているかどうかを確認し、ラベルを更新してください。

+0

提案してくれてありがとうが、私はそれを更新しなければならない...そしてまた実際のコードでは、各関数の後ろにlablesを更新する必要があります。また、14個の関数があります:(そして2つのスレッドは独立したデータを処理しています! – Swanand

関連する問題