2009-07-17 14 views
32

Obiekt BackgroundWorker pozwala przekazać pojedynczy argument do DoWorkEventHandler.Alternatywa dla BackgroundWorker, która akceptuje więcej niż jeden argument?

// 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; 
    ... 
} 

Aby przekazać wiele argumentów, muszę zawinąć je w obiekcie, jak tego biednego tablicy ciągów:

// 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]; 
} 

Czy istnieje inny obiekt lub wzór, który pozwala nam przekazać wiele argumentów ładnie, a najlepiej, napisać własny podpis?

Odpowiedz

45

Można użyć zamknięcie (lambda):

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

Albo z delegata (metoda anonimowy) Składnia:

backgroundWorker.DoWork += 
    delegate(object sender, DoWorkEventArgs e) 
    { 
     MyWorkMethod(userName, targetNumber); 
    }; 
+0

można rozwinąć, jak to działa? (szczególnie "(s, e)" ... dlaczego są zadeklarowane?) –

+0

Bardzo to lubię - dla mojego przypadku użycia działa świetnie, ale bardziej złożone aplikacje mogą mieć problemy, tj. potrzebuję dostępu do parametru wartości (nazwa użytkownika i numer docelowy) w setup/init. –

+1

Cieszę się, że mogę pomóc (i trochę więcej tekstu). –

0

Dlaczego obiekt "jeden" nie jest tablicą parametrów? Musisz tylko odesłać go do tablicy wewnątrz metody z parametru obiektu.

2

Może przekazać funkcję lambda jako Twojego obiektu? Następnie wywołasz to w programie obsługi DoWork.

endCallWorker.RunWorkerAsync(new Action(() => DelegatedCallTarget(userName, targetNumber))); 
+0

czy możesz pokazać mi, jak mogę je rozwinąć w programie obsługi? –

3

Obiekt może być listą lub tablicą lub niektórymi. Po prostu uczyń swój obiekt jakimś pojemnikiem, a następnie rzuć go w BackgroundWorker. Musisz jednak upewnić się, że zawsze przechodzisz przez ten sam typ.

+0

+ McAden Jeśli projektanci biblioteki poradzili sobie z dwoma argumentami, dlaczego nie trzy, cztery itd.? Rozwiązaniem było poradzenie sobie z jednym i to może być obiektem dowolnej złożoności. – DougN

12

Co jest nie tak z użyciem wpisanego obiektu?

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

var args = new UserArgs() {UserName="Me", TargetNumber="123" }; 
startCallWorker.RunWorkerAsync(args); 
+0

To jest ładniejsza niż tablica string [], ale nadal - nie chcę deklarować innej klasy tylko po to, aby przekazywać argumenty do mojej własnej funkcji. Zdarza się to w wielu innych wbudowanych modułach obsługi w .NET - domyślam się, że szukam spójnego wzorca, który nie zanieczyszcza mojego kodu bezużytecznymi klasami opakowania. –

+2

C# 4.0 ma krotkę, która może pomieścić więcej niż jeden argument. Proszę odnieść się do mojej odpowiedzi na to pytanie. –

4

zamiast wpisanego obiektu. C# 4.0 dostarcza nam krotkę. Możemy użyć krotki do przechowywania wielu argumentów. Wtedy nie ma potrzeby deklarowania nowej klasy.

1

utworzyć klasę, która przechowuje wszystkie swoje argumenty

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; 
} 
Powiązane problemy