3

私は BackgroundWorker を試していて、イベントごとにメイン スレッドに通知しようとしています。これらのことはすべて私にとって初めてのことであり、うまくいっているかどうか尋ねたいと思いました.

次の方法で、私のwinformsの問題を単純化しました:(ボタンは1つしかなく、押すと別のスレッドで10までカウントされます)

public partial class Form1 : Form
{
    public void Subscribe(CountToTen c)
    {
        c.HandleWorkerEvent += new CountToTen.WorkerHandler(OtherThreadFinished);
    }
    private void OtherThreadFinished(CountToTen c, EventArgs e)
    {
        Debug.WriteLine("I'm ready !!!");
    }

    public Form1()
    {
        InitializeComponent();
    }

    private void btn_do_Click(object sender, EventArgs e)
    {
        CountToTen newThread = new CountToTen();
        Subscribe(newThread);
        newThread.StartCountingAndReportIfFinished();
    }
}

CountToTen クラス:

public class CountToTen
{

    public event WorkerHandler HandleWorkerEvent;
    public EventArgs e;
    public delegate void WorkerHandler(CountToTen c, EventArgs e);
    public void StartCountingAndReportIfFinished()
    {
        BackgroundWorker worker = new BackgroundWorker();

        worker.DoWork += delegate(object s, DoWorkEventArgs args)
        {
            for (int i = 1; i <= 10; i++)
            {
                Thread.Sleep(300);
                Debug.WriteLine("Counting :" + i.ToString());

            }
        };

        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(delegate(object o, RunWorkerCompletedEventArgs args)
            {
                Debug.WriteLine("Fromt Thread2 : I am finished!");
                if (HandleWorkerEvent != null)
                {
                    HandleWorkerEvent(this, e);
                }
            });

        worker.RunWorkerAsync();
        worker.Dispose();
    }
}

BW が終了したときにイベントを作成し、メイン フォームでこのイベントをサブスクライブしようとしていました。正常に動作しますが、この行で何が起こっているのかよくわかりません:

worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(delegate(object o, RunWorkerCompletedEventArgs args)
            {
                Debug.WriteLine("Fromt Thread2 : I am finished!");
                if (HandleWorkerEvent != null)
                {
                    HandleWorkerEvent(this, e);
                }
            });

BW が終了したら、ここでイベントを作成し、メイン スレッド用に別のイベントを呼び出しませんか? やり過ぎじゃない?RunWorkerCompleteEventHandler にも直接サブスクライブできますか?

ここで少し混乱しています。初心者に教えてください。ありがとう

4

3 に答える 3

2

これは、BackgroundWorker の RunWorkerCompleted イベントへのサブスクリプションです。これは、匿名メソッドまたは名前付きメソッドのいずれかで実行できます。また、次の方法でデリゲート型宣言を削除できます。

worker.RunWorkerCompleted += (o, args) => 
{
    // raise HandleWorkerEvent if there is any subscriber exists
    if (HandleWorkerEvent != null)    
        HandleWorkerEvent(this, e);

    worker.Dispose();
};

名前付きメソッドを使用すると、次のようになります

worker.RunWorkerCompleted += Worker_RunWorkerCompleted;

ハンドラ:

void Worker_RunWorkerCompleted(object o, RunWorkerCompletedEventArgs args)
{
    if (HandleWorkerEvent != null)    
        HandleWorkerEvent(this, e);

    ((BackgroundWorker)o).Dispose();
}

ところで、10 までのロジックしか持たないクラスを用意したほうがよいと思います。フォームに BackgroundWorker を作成し、このクラスを DoWork イベント ハンドラーで使用します。また、フォームはそのすべてのコンポーネントを破棄します。

于 2013-01-18T12:12:42.597 に答える
0
Am I not creating an event here for my BW, when it is finished,
 and then call the another for the main thread?

はい.. CountToTen クラスで BackgroundWorker のイベントを処理しています。そして明らかに、クラスアーキテクチャに従って、イベントを通じてメインフォームに通知する唯一の方法です。

  Is it not overkill? Could I subscribe directly to the RunWorkerCompleteEventHandler
  as well? 

もちろんできます..BackgroundWorkerはメインフォームに直接公開されていません。それ以外の場合は、そこからRunWorkerCompletedEventをサブスクライブできます。

注: Dispose() を呼び出す必要はありません。Component を介して IDisposable インターフェイスを実装します。詳細はこちら

アップデート

  • 別の方法

    public partial class Form1 : Form
    {
      private void btn_do_Click(object sender, EventArgs e)
      { 
        CountToTen obj= new CountToTen();
         obj.bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
         obj.bw.RunWorkerAsync();
       }
    
       void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){}       
    }
    class CountToTen 
    {
    public BackgroundWorker bw = new BackgroundWorker();
    public CountToTen()
    {
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
    }
    
    void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        //Do your Stuff
    }
    }
    
于 2013-01-18T12:22:25.137 に答える
0

BackgroundWorker の RunWorkerCompleted イベントを直接サブスクライブできますが、ビジネス ロジックとアーキテクチャによって異なります。

于 2013-01-18T11:58:22.923 に答える