2011-03-29 14 views
2

私は非同期メソッドのためにEAPを実装したオブジェクトを含むアセンブリ(.NETクラスライブラリ)があります。BackgroundWorkerを使用してイベントベースの非同期パターンを実装する必要がありますか?

class Product 
{ 
    void Install(); 
    void InstallAsync(); 
    EventHandler<InstallProgressChangedEventArgs> Installing; 
    EventHandler<InstallCompletedEventArgs> Installed; 
} 

私は「標準」Threadを使用するか、.NETが提供するBackgroundWorkerクラスを使用するかどうかを考えていますが。

I've read「Windowsフォーム」またはUIでオブジェクトが使用されることが予想される場合は、BackgroundWorkerを使用する必要があります。私が書いているクラスライブラリは、Windowsフォーム、WPFアプリケーションとコンソールアプリケーションで使用できます。私はBackgroundWorkerクラスを使用していた場合

また、それはBackgroundWorkerクラスからないサブクラスに「正しい」とは?私は自分のイベント(インストールとインストール)を提供するので、クラスのメンバーを公開したくありません。

BackgroundWorkerクラスが適切でない場合は、何をお勧めしますか?その理由は何ですか?

答えて

4

は外BWコンポーネントを使用しても問題ありませんWindowsフォームアプリケーションのUIアプリケーション。バックグラウンドスレッドを簡単に起動し、その作業が完了したときにコールバックを受け取る必要がある場合にのみ使用されます。

唯一の必要条件は、スレッドを起動して結果を取得し、スレッドを自分で管理する必要がない場合は、使用することをお勧めします。

コンポーネントをバックグラウンドワーカーにしない限り、私はそれをサブクラス化しません。つまり、あなたはその行動を拡張しています。単にその振る舞いを使用しているのであれば、サブクラス化する必要はなく、作曲を使うだけです。

+0

さて、このようなBGWを使用すると問題がありますが、MSDNライブラリで説明されているように動作しません。実際にそれを使用することには意味がありません。イベントはすべてtpスレッドで実行されます。同様のスレッドを使用することもできます。 –

+0

「MSDNで記述されているように動作しませんか? – Andy

1

私はThreadPoolのを使用することをお勧めします。

ThreadPool.QeueuUserWorkItem((_state)=>{ this.OnInstalling(...); }); 

EDIT:

BackgroundWorkerのは、 "スリム" である代わりにThreadPoolのを使用します。 BackGroundWorkerは、 "マルチスレッドのもの"をすべてカプセル化した "大きな"インスタンスを作成する必要がありますが、内部のBuckgroundWorkerはThreadおよび/またはThreadPoolを使用しています(どちらが覚えていないか)。

スレッドの代わりにThreadPoolを使用すると、(ThreadPoolに送信された)アクションが完了すると、将来、別のアクションにスレッドが再利用されるため、パフォーマンスが向上します。しかし、作成新しいスレッドは、 "高価な"操作、スレッドを再利用する "安い"です。

EDIT 2:

あなたは、多くの場合、「素敵」な方法は、そのための拡張メソッドを使用しているparalelスレッドでイベントを発生させたい場合は:

class Product { 
    public void Install() { 
     this.OnInstalling(...); 
     ... 
     this.OnInstalled(...); 
    } 
    public void InstallAsync() { 
     this.OnInstallingAsync(...); 
     ... 
     this.OnInstalledAsync(...); 
    } 

    protected virtual void OnInstalling(InstallProgressChangedEventArgs e) { 
     this.Installing.Raise(this, e); 
    } 
    protected virtual void OnInstallingAsync(InstallProgressChangedEventArgs e) { 
     this.Installing.RaiseAsync(this, e); 
    } 
    public event EventHandler<InstallProgressChangedEventArgs> Installing; 

    protected virtual void OnInstalled(InstallCompletedEventArgs e) { 
     this.Installed.Raise(this, e); 
    } 
    protected virtual void OnInstalledAsync(InstallCompletedEventArgs e) { 
     this.Installed.RaiseAsync(this, e); 
    } 
    public event EventHandler<InstallCompletedEventArgs> Installed; 
} 
// ... 
public static class EventExtensions { 
    public static void Raise(this EventHandler handler, object sender, EventArgs e) { 
     if (null != handler) { handler(sender, e); } 
    } 

    public static void Raise<TEventArgs>(this EventHandler<TEventArgs> handler, object sender, TEventArgs e) where TEventArgs : EventArgs { 
     if (null != handler) { handler(sender, e); } 
    } 

    public static void RaiseAsync(this EventHandler handler, object sender, EventArgs e) { 
     if (null != handler) { 
      ThreadPool.QeueuUserWorkItem((_state)=>{ handler(sender, e); }); 
     } 
    } 

    public static void RaiseAsync<TEventArgs>(this EventHandler<TEventArgs> handler, object sender, TEventArgs e) where TEventArgs : EventArgs { 
     if (null != handler) { 
      ThreadPool.QeueuUserWorkItem((_state)=>{ handler(sender, e); }); 
     } 
    } 
} 
+0

返信いただきありがとうございます。 ThreadPoolが推奨される理由を教えてください。 – Ian

+0

いくつかの作業を行うたびにスレッドを作成するためのリソースを無駄にしないため、スレッドプールを持つスレッドプールは素晴らしいです。 –

+0

BackgroundWorkerコンポーネントは、作業をしたいときにThreadPoolスレッドも使用します。 – Andy

関連する問題