2016-12-23 4 views
0

複数の小さなアプリケーションを開発する際に、バックグラウンドタスクに新しいスレッドを使用することができます。私はいくつかのオプション、主にバックグラウンドワーカーと代理人を試しました。私がやりたいことは、すべてのスレッドを実行するための専用のスレッドクラスを用意して、複数のプログラムで再利用できるようにすることです。スレッドを処理するためのクラスを作成する

私はこの場所で読むべきか、見ているか、何をすべきかについてのガイダンスを探しています。私は今、失敗するかの

例:

メインスレッド(GUI) ユーザーは、いくつかのロジックを通過し、(完全な計算まで、GUIを凍結するだろう)、複数のタスク集中的な計算を開始し、ボタン1をクリック開始します。私がやりたいのは何

はこのような何か..です

メインスレッド(GUI)は ユーザーが何らかの GUIスレッドのレポートのリストにエンキュースレッドプロセスとして進行スレッドを作成Button1をクリック開始します計算 スレッド終了とデキュー後で (潜在的に?)バックグラウンドでループしているスレッドクラスは、アイテムがエンキューして処理されるのを待っています。

小さなタスクのための私の典型的な方法は

Thread fooThread= new Thread((ThreadStart)delegate 
    { 
     //command 
    }); 

    fooThread.Start(); 

問題がある、私のボタンイベントは、それらに追加のアイテムを持っている(多分、私はそれらをリファクタリングしてください)

サンプル

private void btnCopy_Click(object sender, EventArgs e) 
{ 
    //check file exists, check destination exists, etc 
    //start new thread 

    Thread fooThread= new Thread((ThreadStart)delegate 
    { 
     //copy files to destination using method foobarCopy(params) 
    }); 

    fooThread.Start(); 

//if file copy is successful, inform user on GUI. 
} 

I主に.NET2.0を使用していますが、必要に応じて4.5までバンプすることができます。

+0

ボタンクリックのコードはおそらくあなたのクラスであるはずです。 'FileCopier'や' Start() 'との間には何もありません。それが完了し、通知があなた次第であるかどうかを判断しますが、それは本当にあなたのクラスです。独自のスレッドマネージャクラスを作成する必要はないと思いますが、そのコードをビジネスオブジェクトにリファクタリングして、そこからリファクタリングする次のものの基本クラスを作ることができます。 – TyCobb

+2

既存のスレッドプールサポートを使用するほうがよいでしょう。 –

+0

おそらく、非同期コールバックメソッドを使用してguiの結果を操作するか、アスペクト指向のフレームワークチェックを使用するか、spring.net aopのようなロジック、データなどを制御する必要があります。 – FreeMan

答えて

0

アプリケーションを.Net 4.5にアップグレードすると、簡単に操作できます。 await-async構造を持つタスクとタスク並列ライブラリ(TPL)インフラストラクチャを活用できます。

今日の.NETの時代には、既存のスレッドプールを活用するのではなく、自分のスレッドを手動で作成する理由が本当に説得力のある理由が必要です。このような理由の1つは、あなたのプロセスで作成された新しいスレッドを以下の理由で絶対的に制御しようとした場合です:

  • スレッドを作成する必要がありますか?
  • プロセスでいくつの新しいスレッドを作成する必要がありますか?
  • スレッドを削除する必要がありますか?
  • OSスケジューリングアルゴリズムのスタンドポイントからの新しいスレッドの優先順位はどのようにする必要がありますか?例えば高、中、低
  • 私のスレッドはバックグラウンドスレッドかフォアグラウンドスレッドか?

一般的なビジネスアプリケーションのアプリケーションでは、スレッドを細かく制御する必要はほとんどありません。

タスクはフリーズされたUIの問題を取り除くのを手助けする親友です。詳細は、私のブログhereをご覧ください。あなたのコードを書き直す方法は次のとおりです。

private async void btnCopy_Click(object sender, EventArgs e) 
{ 
    //check file exists, check destination exists, etc 
    string sourceFile = @"C:\a.txt", destinationFile = @"C:\b.txt"; 
    //Let TPL do the heavy lifting of interacting with disk for I/O 
    var copyTask = await CopyFile(sourceFile, destinationFile); 

    /* 
    //Manual thread instantiation not needed. Hence commented 
    Thread fooThread = new Thread((ThreadStart)delegate 
    { 
     //copy files to destination using method foobarCopy(params) 
    }); 

    fooThread.Start(); 
    */ 

    //if file copy is successful, inform user on GUI. 
    if (copyTask) 
    { 
     //show a message box 
    } 
} 

private async Task<bool> CopyFile(string sourceFile, string destinationFile) 
{ 
    bool fileCopiedSuccessfully = true; 
    //here use async I/O methods from stream class which support the notion of tasks 
    try 
    { 
     using (FileStream sourceStream = File.Open(sourceFile, FileMode.Open)) 
     { 
      using (FileStream destinationStream = File.Create(destinationFile)) 
      { 
       //exactly at this point of time when the actual copy happens your GUI thread is completely 
       //free to do anything. It won't freeze. 
       //This work happens on a thread-pool thread which you don't have to worry about. 
       await sourceStream.CopyToAsync(destinationStream); 
      } 
     } 
    } 
    catch (IOException ioex) 
    { 
     fileCopiedSuccessfully = false; 
     MessageBox.Show("An IOException occured during copy, " + ioex.Message); 
    } 
    catch (Exception ex) 
    { 
     fileCopiedSuccessfully = false; 
     MessageBox.Show("An Exception occured during copy, " + ex.Message); 
    } 
    return fileCopiedSuccessfully ; 
} 
関連する問題