2010-12-01 16 views
2

私は現在、マルチスレッド化することでwinformアプリケーションのパフォーマンスを向上させようとしています。現在、クラスは次のようになります。マルチスレッドによるパフォーマンスの向上

public class MainClass 
{ 
    List<DataItem> data; //thousands of DataItem, but each is independent 

    //and a lot of non-thread-safe variables here,variable1 variable2 ... 

    public void Go() 
    { 
     data.ForEach(item => DealWithDataItem(item)); 
    } 

    public void DealWithDataItem(DataItem item) 
    { 
     //costs really long time here 
     Step1(item); 
     Step2(item); //and a lot of StepN(item) 
    } 

    public void StepN(DataItem item) 
    { 
     //variable1 = blabla 
     //variable2 = blabla ..etc 
    } 
} 

私はそれぞれのDataItemのためThreadPoolを使用したいです。

data.ForEach(item => ThreadPool.QueueUserWorkItem(s => DealWithDataItem(item))); 

非常に多くのスレッドセーフではない変数です。私はStepNメソッドの間で共有されているので、何らかの方法でそれらを宣言することはできません。そして、それらをスレッドセーフにすることは非常に難しいです!私は間違って何かしていますか?良い解決策はありますか?ありがとう!

+0

は十分なバックグラウンドではありませんか? –

+1

それは本当にあなたが変数1で何をするかによって決まります。彼らは値を合計しますか?読みますか?書きます?これらの変数の使用法については、より具体的に説明する必要があります。さまざまな使用パターンにはさまざまなソリューションがあります。 –

+0

わかりません。'MainClass'はすべての' DataItem'の進捗状況を処理する全体的な進捗状況を監視するものです(MainClassの状態として必要です)。そうでない場合は、作業ごとに個別のオブジェクトを作成することを検討してください。 –

答えて

3

ParallelEnumerable.AsParallelをお試しください。

data.AsParallel.ForEach(DoWork); 

プロセッサ/コアの量によってスレッドが自動的に作成されます。 唯一の問題は、Framework 4.0に含まれていることです。 さらに詳しい情報はPLINQです。

UPD:(framwork 3.5のために、それはスタンドアローンReactive Extensions (Rx)として利用可能であるアンドラーシュがコメントとしてAND):0xA3のが言ったように、コードのリファクタリング、各項目を作るにはそれ自身のCALC変数を持っていることを強くお勧めします。 計算ロジックをDataItemに抽出することをお勧めします。

また、すべての作業を行う「電卓」のような特別なクラスを作成すると、DataItemはデータのみを格納し、計算のロジックはCalculatorクラスに含まれます。電卓クラスは、この

class Calculator 
{ 
    // variables here 

    void DoWork(DataItem item) 
    { 
    Step1(item); 
    Step2(item); 
    // ... 
    // StepN(item); 
    } 
} 
+0

Rxライブラリで.NET 3.5の 'Parallel.ForEach'と他の多くのものが見つかります。 http://codeblog.theg2.net/2010/02/tpl-and-parallelforeach-in-net-35-using.html –

+0

@andrasありがとうございます、回答を更新します –

0

のようなものであるおそらく最良の方法は、あなたが異なるデータ項目間で共有フィールドそのすべてを取り除くように、あなたのコードをリファクタリングすることです

data.AsParallel.ForEach(x=> new Calculator().DoWork(x)); 

変更(またはサブクラス)dataItemを操作するためのすべての関連データとメソッドを格納するためのDataItemクラス、このようなものになるようにあなたのコードの変更:

public void DealWithDataItem(DataItem item) 
{ 
    item.Step1(); // does not change the state of `this` 
        // and only changes variables that are private to `item` 
    item.Step2(); // and a lot of StepN(item) 
} 
0

それぞれのDataItemが独立しているため、移動新しいのDataItemワーカーメソッドに作業し、自分自身で各インスタンスの契約をしてみましょう:

public class MainClass 
{ 
    List<DataItem> data; //thousands of DataItem, but each is independent 

    public void Go() 
    { 
     data.ForEach(item => ThreadPool.QueueUserWorkItem(s => s.DealWithSelf())); 
    } 
} 

public class DataItem 
{ 
    //and a lot of non-thread-safe variables here,variable1 variable2 ... 

    void DealWithSelf() 
    { 
     //costs really long time here 
     Step1(item); 
     Step2(item); //and a lot of StepN(item) 
    } 

    public void StepN(DataItem item) 
    { 
     //variable1 = blabla 
     //variable2 = blabla ..etc 
    } 
} 
0

は、あなたのGUIのスレッドでMainClassですか?あなたはGUIスレッドでデータ処理を行うべきではありません。 MainClassを別のスレッドで実行してください。

これを行う方法?それはあなたが私たちに示されていないものであるblablaに完全に依存します。 MainClassは結果を返す必要がありますか? BeginInvoke/EndInvokeを使用してください。 GUIを更新する必要がありますか? BackgroundWorkerを使用してください。より良い回答が必要な場合は、より多くの情報を提供する必要があります。

関連する問題