3


2

バックグラウンドワーカーのdoworkにメソッドを渡す

以下のコードには、常にupdateWorker_DoWorkメソッドをサブスクライブする代わりに、このようなメソッドを渡す方法があります

public void GetUpdates(SomeObject blah)
{
    //...
    updateWorker.DoWork += new DoWorkEventHandler(blah);
    //...
}


public void GetUpdates()
{
    //Set up worker
    updateWorker.WorkerReportsProgress = true;
    updateWorker.WorkerSupportsCancellation = true;
    updateWorker.DoWork += new DoWorkEventHandler(updateWorker_DoWork);
    updateWorker.RunWorkerCompleted +=
        new RunWorkerCompletedEventHandler(updateWorker_RunWorkerCompleted);
    updateWorker.ProgressChanged +=
        new ProgressChangedEventHandler(updateWorker_ProgressChanged);

    //Run worker
    _canCancelWorker = true;
    updateWorker.RunWorkerAsync();
    //Initial Progress zero percent event
    _thes.UpdateProgress(0);
}

3 Answer


3


`RunWorkerAsync()`には、好きな引数を渡すことができます。 `Func()`または `Action()`をそこに置くだけで、 `DoWork()`でオブジェクトをこの特定の型にキャストして呼び出します。

例はhttps://stackoverflow.com/questions/1902384/make-a-backgroundworker-do-several-operations-sequentially-without-freezing-the-f/1907501#1907501[here]およびhttps://stackoverflow.comです。 / questions / 2183520 / backgroundworkers-never-stop-being-busy / 2183963#2183963 [こちら]。

private void InitializeBackgroundWorker()
{
    _Worker = new BackgroundWorker();

    // On a call cast the e.Argument to a Func and call it...
    // Take the result from it and put it into e.Result
    _Worker.DoWork += (sender, e) => e.Result = ((Func)e.Argument)();

    // Take the e.Result and print it out
    // (cause we will always call a Func the e.Result must always be a string)
    _Worker.RunWorkerCompleted += (sender, e) =>
    {
        Debug.Print((string)e.Result);
    };
}

private void StartTheWorker()
{
    int someValue = 42;

    //Take a method with a parameter and put it into another func with no parameter
    //This is called currying or binding
    StartTheWorker(new Func(() => DoSomething(someValue)));

   while(_Worker.IsBusy)
       Thread.Sleep(1);

   //If your function exactly matches, just put it into the argument.
   StartTheWorker(AnotherTask);
}

private void StartTheWorker(Func func)
{
    _Worker.RunWorkerAsync(func);
}

private string DoSomething(int value)
{
    return value.ToString("x");
}

private string AnotherTask()
{
    return "Hello World";
}


2


誤解しない限り、匿名メソッドを構築するにはラムダ式が必要です。

updateWorker.DoWork += (sender,e)=>
  {
      //bla
  }

これで、常にメソッドを作成してそれを `new DoWorkEventHandler(myMethod)`に渡す必要がなくなりました


1


私が考えていたよりもずっと簡単だった。 DoWorkで呼び出されるメソッドのデリゲートを作成する必要がありました。 おそらく、元の質問をより適切に表現する必要がありました。

    public delegate void DoWorkDelegate(object sender,DoWorkEventArgs e);

     public void GetUpdates()
     {
         StartWorker(new DoWorkDelegate(updateWorker_DoWork));
     }

     public void StartWorker(DoWorkDelegate task)
     {
         //Set up worker
         updateWorker.WorkerReportsProgress = true;
         updateWorker.WorkerSupportsCancellation = true;
         updateWorker.DoWork += new DoWorkEventHandler(task);
         updateWorker.RunWorkerCompleted +=
             new RunWorkerCompletedEventHandler(updateWorker_RunWorkerCompleted);
         updateWorker.ProgressChanged +=
             new ProgressChangedEventHandler(updateWorker_ProgressChanged);

         //Run worker
         _canCancelWorker = true;
         updateWorker.RunWorkerAsync();
         //Initial Progress zero percent event
         _thes.UpdateProgress(0);
     }

      private void updateWorker_DoWork(object sender, DoWorkEventArgs e)
      {
          BackgroundWorker worker = sender as BackgroundWorker;
          e.Result = GetUpdatesTask(worker, e);
      }