2016-12-07 13 views
0

大きなエクセル(10kレコード)を処理しています。このプロセスを複数のスレッドで実行してパフォーマンスを向上させる必要があります。行を複数の等しいロットに分割し、繰り返し処理する方法

今は行< = 2000の場合はチェックしていますが、Utils.IxGenerateWithDataをすべてのレコードで正常に実行できます。しかし、行> 2000(たとえば10k)の場合、これらを複数のスレッドに分割してUtils.IxGenerateWithDataを処理し、それぞれ2000個のレコードで記録したいと考えています。

using (Stream contentStream = await requestContent.ReadAsStreamAsync()) 
          { 
           Workbook workbook = new Workbook(contentStream); 
           Worksheet worksheet = workbook.Worksheets[0]; 
           int column = 0; // first column 
           Cell lastCell = worksheet.Cells.EndCellInColumn((short)column); 

           //Run on multiple threads if the file has more than 2000 records 
           if (lastCell.Row > 2000) 
           { 

            //Not sure what to do here 



            // Infiniti GenerateWithData Web Service 
            Thread thread = new Thread(() => Utils.IxGenerateWithData(payloadSettings.ProjectGUID, payloadSettings.DatasourceGUID, xmlContent, payloadSettings.InfinitiUsername, payloadSettings.InfinitiPassword, payloadSettings.ServiceWSDL)); 
            thread.Start(); 
           } 
           else 
           { 
            for (int row = 0; row <= lastCell.Row; row++) 
            { 
             Cell cell = worksheet.Cells.GetCell(row, column); 
             xmlContent += cell.StringValueWithoutFormat; 
            } 

            // Infiniti GenerateWithData Web Service 
            Utils.IxGenerateWithData(payloadSettings.ProjectGUID, payloadSettings.DatasourceGUID, xmlContent, payloadSettings.InfinitiUsername, payloadSettings.InfinitiPassword, payloadSettings.ServiceWSDL); 
           }        
          } 
+0

私はあなたが助けることができるかどうかは分かりませんが、なぜ「利回り」を使用しないのですか? http://www.ytechie.com/2009/02/using-c-yield-for-readability-and-performance/ –

答えて

0

良いスタートを開始したいどのように多くのスレッドを決定することです助けてください。

var threadCount = (lastCell.Row/2000) + 1; 

1は、スレッドは2000の以上の行を持つことはありませんが、それはあまりを持つことができることを保証するために追加されます:あなたは、スレッドごとに2000行に行くされている場合は、次のようにTHREADCOUNTが計算されます。次のように

そしてrowsPerThreadを計算する:

var rowsPerThread = lastCell.Row/threadCount; 

は、最後にそれをそれが処理すべき行の配列を渡すスレッドを開始するためのループを持っています。ここでは、forループで作成されたクラスを作成し、処理する必要がある行をコンストラクタで渡します。次に、オブジェクト内の行を処理するスレッドを開始するStartメソッドを用意します。

ようになり、このようなクラスの概要は次のとおりです。

public class ExcelRowProcessor() 
{ 
    private List<ExcelRow> _rows = new List<ExcelRow>(); 
    public ExcelRowProcessor(IEnumerable<ExcelRow> rows) 
    { 
     _rows.AddRange(rows); 
    } 

    public void Start() 
    { 
     // Start the thread here. 
    } 
} 

私はこのことができます願っています。

+0

スレッド数を決定し、スレッドごとに行を計算します。私はこのforループを持っています(int threadNum = 0; threadNum <= threadCount; threadNum ++) { リストセル=新しいリスト(); cells.AddRange(); }私が理解できないことは、ループの最初の実行が1から2000までで、2度目の実行が2001からなどになることを確認する方法です – harpermartin

0

この回答を新しいものにして申し訳ありませんが、まだJacoに投稿できるという評判はまだありません。

とにかく、一般的に、ワークロード/バケットサイズに基づいてスレッドの数を決定する必要はありません。 CPUコアの数に基づいてバケットサイズを決定する方が良いです。これはスレッドの切り替えを防止するためのもので、OS/Virusスキャナ用の1つのコアも同様に役立ちます。 How to find the Number of CPU Cores via .NET/C#?

var threadCount = cpuCoreCount - 1; //TODO: use code from above URL 
if (0 == threadCount) { 
    threadCount = 1; 
} 
var rowsPerThread = lastCell.Row/threadCount; // As Jaco posted 

だから、バックスレッド方法については、あなたの質問に:

using (Stream contentStream = await requestContent.ReadAsStreamAsync()) 
{ 
    Workbook workbook = new Workbook(contentStream); 
    Worksheet worksheet = workbook.Worksheets[0]; 
    int column = 0; // first column 
    Cell lastCell = worksheet.Cells.EndCellInColumn((short)column); 
    List<IAsyncResult> asyncResults = new List<IAsyncResult>(); 
    string xmlContent = ""; // assuming this is local 


    for (int row = 0; row <= lastCell.Row; row++) 
    { 
     Cell cell = worksheet.Cells.GetCell(row, column); 
     xmlContent += cell.StringValueWithoutFormat; 

     if (((row > 0) && (row % rowsPerThread == 0)) || (rows == lastCell.Row)) 
     { 
      var caller = new GenerateDelegate(Generate); 
      asyncResults.Add(caller.BeginInvoke(xmlContent, null, null)); 
      xmlContent = ""; 
     } 
    } 

    // Wait for the threads 
    asyncResults.ForEach(result => { 
     while(result.IsCompleted == false) { 
      Thread.Sleep(250); 
     } 
    }); 
} 

置き、このコードは関数の外でこの記事を参照してください...スレッド/コア/プロセス数を取得するには

private delegate void GenerateDelegate(string xmlContent); 

///<summary> 
/// Call Infiniti GenerateWithData Web Service 
///<summary> 
private void Generate(string xmlContent) 
{ 
    Utils.IxGenerateWithData(payloadSettings.ProjectGUID, payloadSettings.DatasourceGUID, xmlContent, payloadSettings.InfinitiUsername, payloadSettings.InfinitiPassword, payloadSettings.ServiceWSDL); 
} 
関連する問題