2009-07-17 11 views
32

El objeto BackgroundWorker nos permite pasar un solo argumento al DoWorkEventHandler.¿Alternativa a BackgroundWorker que acepta más de un argumento?

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

pasar múltiples argumentos, debo envolverlos en un objeto, como este pobre matriz de cadenas:

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

¿Hay otro objeto o patrón que nos permite pasar múltiples argumentos muy bien, o, idealmente, escribe nuestra propia firma?

Respuesta

45

Se puede usar un cierre (Lambda):

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

O con el delegado (método anónimo) sintaxis:

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

Podría explicar cómo funciona esto? (especialmente el "(s, e)" ... ¿por qué están declarados?) –

+0

Me gusta mucho - Para mi caso de uso, funciona muy bien, pero las aplicaciones más complejas pueden tener problemas, es decir, necesito acceder al parámetro values ​​(username y targetNumber) en setup/init. –

+1

Me alegra ayudar (y algo más de texto). –

0

¿Por qué no pasar el objeto "uno" a una matriz de parámetros? Solo necesita devolverlo a la matriz dentro del método desde el parámetro del objeto.

2

pasan Tal vez una función lambda como su objeto? Entonces lo llamarías en el controlador DoWork.

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

¿podría mostrarme cómo desenvuelvo en el controlador? –

3

El objeto puede ser una lista o matriz o algo así. Simplemente haga que su objeto sea un contenedor de algún tipo, luego colóquelo en BackgroundWorker. Sin embargo, debes asegurarte de que siempre pasas el mismo tipo.

+0

+ McAden Si los diseñadores de la biblioteca manejaron dos argumentos, ¿por qué no tres, cuatro, etc.? La solución fue manejar uno, y ese puede ser un objeto de complejidad arbitraria. – DougN

12

¿Qué pasa con el uso de un objeto tipado?

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

Esto es más bonito que mi matriz de cadena [], pero aún así, no quiero declarar otra clase solo para pasar argumentos a mi propia función. Esto sucede en muchos otros controladores incorporados en .NET. Supongo que estoy buscando un patrón consistente que no contamine mi código con clases de envoltura inútiles. –

+2

C# 4.0 tiene una tupla que podría contener más de un args. Por favor, consulte mi respuesta a esta pregunta. –

4

en lugar de un objeto tipeado. C# 4.0 nos proporciona tupla. Podríamos usar una tupla para contener múltiples args. Entonces no hay necesidad de declarar una nueva clase.

1

Crear una clase que tiene todos sus argumentos

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; 
} 
Cuestiones relacionadas