Альтернатива BackgroundWorker, которая принимает несколько аргументов?
Объект 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];
}
Есть ли другой объект или шаблон, который позволяет нам передать несколько аргументов красиво или, в идеале, написать нашу собственную подпись?
Ответы
Ответ 1
Вы можете использовать закрытие (Lambda):
backgroundWorker.DoWork += (s, e) => MyWorkMethod(userName, targetNumber);
Или с синтаксисом делегата (анонимный метод):
backgroundWorker.DoWork +=
delegate(object sender, DoWorkEventArgs e)
{
MyWorkMethod(userName, targetNumber);
};
Ответ 2
Что не так с использованием типизированного объекта?
internal class UserArgs
{
internal string UserName { get; set; }
internal string TargetNumber { get; set; }
}
var args = new UserArgs() {UserName="Me", TargetNumber="123" };
startCallWorker.RunWorkerAsync(args);
Ответ 3
вместо типизированного объекта. С# 4.0 предоставляет нам кортеж. Мы могли бы использовать кортеж для хранения нескольких аргументов. Тогда нет необходимости объявлять новый класс.
Ответ 4
Объектом может быть список или массив или некоторые из них. Просто сделайте свой объект каким-то контейнером, а затем бросите его в BackgroundWorker. Вы должны убедиться, что вы всегда проходите в том же типе.
Ответ 5
Может быть, передать объект лямбда-функции в качестве объекта? Затем вы будете называть его в обработчике DoWork.
endCallWorker.RunWorkerAsync(new Action( () => DelegatedCallTarget(userName, targetNumber) ));
Ответ 6
Создайте класс, содержащий все ваши аргументы
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;
}
Ответ 7
Почему бы не передать "один" объект как массив параметров? Вам нужно только вернуть его в массив внутри метода из параметра объекта.