Альтернатива BackgroundWorker, которая принимает более одного аргумента? - PullRequest
32 голосов
/ 18 июля 2009

Объект BackgroundWorker позволяет нам передать один аргумент в DoWorkEventHandler.

// setup/init:
BackgroundWorker endCallWorker = new BackgroundWorker();
endCallWorker.DoWork += new DoWorkEventHandler(EndCallWorker_DoWork);
...
endCallWorker.RunWorkerAsync(userName);

// the handler:
private void EndCallWorker_DoWork(object sender, DoWorkEventArgs e)
{
    string userName = e.Argument as string;
    ...
}

Чтобы передать несколько аргументов, я должен обернуть их в объект, такой как этот массив плохих строк:

// setup/init:

BackgroundWorker startCallWorker = new BackgroundWorker();
startCallWorker.DoWork += new DoWorkEventHandler(StartCallWorker_DoWork);
...
startCallWorker.RunWorkerAsync(new string[]{userName, targetNumber});


// the handler:
private void StartCallWorker_DoWork(object sender, DoWorkEventArgs e)
{
    string[] args = e.Argument as string[];
    string userName = args[0];
    string targetNumber = args[1];
}

Есть ли другой объект или шаблон, который позволяет нам красиво передавать несколько аргументов или в идеале написать собственную подпись?

Ответы [ 7 ]

45 голосов
/ 18 июля 2009

Вы можете использовать замыкание (лямбда):

backgroundWorker.DoWork += (s, e) => MyWorkMethod(userName, targetNumber);

Или с синтаксисом делегата (анонимный метод):

backgroundWorker.DoWork += 
    delegate(object sender, DoWorkEventArgs e)
    {
        MyWorkMethod(userName, targetNumber);
    };
12 голосов
/ 18 июля 2009

Что не так с использованием типизированного объекта?

internal class UserArgs
{
    internal string UserName { get; set; }
    internal string TargetNumber { get; set; }
}

var args = new UserArgs() {UserName="Me", TargetNumber="123" };
startCallWorker.RunWorkerAsync(args);
4 голосов
/ 14 июня 2011

вместо типизированного объекта. C # 4.0 предоставляет нам кортеж. Мы могли бы использовать кортеж для хранения нескольких аргументов. Тогда нет необходимости объявлять новый класс.

3 голосов
/ 18 июля 2009

Объект может быть списком или массивом или чем-то подобным. Просто сделайте ваш объект каким-то контейнером, а затем приведите его в BackgroundWorker. Вы должны убедиться, что вы всегда передаете один и тот же тип.

2 голосов
/ 18 июля 2009

Может быть, передать лямбда-функцию в качестве вашего объекта? Затем вы вызываете его в обработчике DoWork.

endCallWorker.RunWorkerAsync(new Action( () => DelegatedCallTarget(userName, targetNumber) ));
1 голос
/ 25 октября 2011

Создайте класс, содержащий все ваши аргументы

Class MyClass
{
     private string m_Username = string.Empty;
     private int m_Targetnumber;

     public MyClass(){}

     public string Username
     {
         get { return m_Username; }
         set { m_Username = value; }
     }

     public int TargetNumber
     {
         get { return m_TargetNumber; }
         set { m_TargetNumber = value; }
     }
 }



// setup/init:

BackgroundWorker startCallWorker = new BackgroundWorker();
startCallWorker.DoWork += new DoWorkEventHandler(StartCallWorker_DoWork);
...

MyClass thisClass = new MyClass();
thisClass.Username = "abcd";
thisClass.TargetNumber = 1234;
startCallWorker.RunWorkerAsync(thisClass);


// the handler:
private void StartCallWorker_DoWork(object sender, DoWorkEventArgs e)
{
     MyClass args = (MyClass)e.Argument;
     string userName = args.Username;
     string targetNumber = args.TargetNumber;
}
0 голосов
/ 18 июля 2009

Почему передаваемый объект "one" не является массивом параметров? Вам нужно только привести его обратно к массиву внутри метода из параметра объекта.

...