Tome el método System.Windows.Forms.Control.Invoke (método Delegate)
¿Por qué esto da un error de tiempo de compilación?
string str = "woop";
Invoke(() => this.Text = str);
// Error: Cannot convert lambda expression to type 'System.Delegate'
// because it is not a delegate type
Sin embargo, esto funciona bien:
string str = "woop";
Invoke((Action)(() => this.Text = str));
Cuando el método espera un delegado simple?
Invoke(()=>DoStuff)
y aún recibí el error. El problema fue que usé el implícito 'esto'. Para conseguir que funcione desde el interior de un órgano de control que tiene que ser explícito:this.Invoke(()=>DoStuff)
.¿Cansado de lanzar lambdas una y otra vez?
fuente
Lambda<T>
clase tiene un método de conversión de identidad llamadoCast
, que devuelve todo lo que se pasa (Func<T, T>
). AhoraLambda<T>
se declara como loLambda<Func<int, string>>
que significa que si pasa un métodoFunc<int, string>
toCast
, regresaFunc<int, string>
, ya queT
en este caso esFunc<int, string>
.Nueve décimas de las veces las personas obtienen esto porque están tratando de reunir el hilo de la interfaz de usuario. Aquí está la manera perezosa:
Ahora que está escrito, el problema desaparece (qv Skeet's anwer) y tenemos esta sintaxis muy sucinta:
Para puntos de bonificación aquí hay otro consejo. No haría esto para las cosas de la interfaz de usuario, pero en los casos en que necesite SomeMethod para bloquear hasta que se complete (por ejemplo, E / S de solicitud / respuesta, esperando la respuesta) use un WaitHandle (qv msdn WaitAll, WaitAny, WaitOne).
Tenga en cuenta que AutoResetEvent es un derivado WaitHandle.
Y un consejo final porque las cosas pueden enredarse: WaitHandles detiene el hilo. Esto es lo que se supone que deben hacer. Si intentas reunir el hilo de la interfaz de usuario mientras lo tienes bloqueado , tu aplicación se bloqueará. En este caso (a) es necesaria una refactorización seria, y (b) como un truco temporal puede esperar así:
fuente
System.Windows.Threading.Dispatcher.CurrentDispatcher
devolverá el despachador del subproceso ACTUAL, es decir, si llama a este método desde un subproceso que no es el subproceso de la interfaz de usuario, el código no se ejecutará en el subproceso de la interfaz de usuario.Peter Wone eres un hombre Llevando su concepto un poco más allá, se me ocurrieron estas dos funciones.
Coloco estas dos funciones en mi aplicación Form, y puedo hacer llamadas de trabajadores en segundo plano como este
Tal vez sea un poco vago, pero no tengo que configurar las funciones realizadas por el trabajador, lo cual es muy útil en casos como este
Esencialmente, obtenga algunas direcciones IP de un DataGridView gui, haga ping, configure los iconos resultantes en verde o rojo y vuelva a habilitar los botones en el formulario. Sí, es un "paralelo. Para" en un trabajador de fondo. Sí, es MUCHA invocación de gastos generales, pero es insignificante para listas cortas y código mucho más compacto.
fuente
Traté de construir esto sobre la respuesta de @Andrey Naumov . Puede ser que esto sea una ligera mejora.
Donde parámetro de tipo
S
es el parámetro formal (el parámetro de entrada, que es el mínimo requerido para inferir el resto de los tipos). Ahora puedes llamarlo así:Puede tener sobrecargas adicionales para
Action<S>
y deExpression<Action<S>>
manera similar en la misma clase. Por otra construida en delegado y expresión tipos, tendrá que escribir clases separadas comoLambda
,Lambda<S, T>
,Lambda<S, T, U>
etc.Ventaja de esto que veo sobre el enfoque original:
Una especificación de tipo menos (solo se necesita especificar el parámetro formal).
Lo que le da la libertad de usarlo contra cualquiera
Func<int, T>
, no solo cuandoT
se dicestring
, como se muestra en los ejemplos.Admite expresiones de inmediato. En el enfoque anterior, tendrá que especificar tipos nuevamente, como:
para expresiones
Ampliar la clase para otros tipos de delegado (y expresión) es igualmente engorroso como el anterior.
En mi enfoque, debe declarar tipos solo una vez (eso también es menos para
Func
s).Otra forma de implementar la respuesta de Andrey es como no ser completamente genérico
Entonces las cosas se reducen a:
Eso es aún menos mecanografía, pero pierde cierta seguridad de tipografía, y eso no vale la pena.
fuente
Un poco tarde para la fiesta, pero también puedes emitir así
fuente
fuente
Jugando con XUnit y Fluent Assertions fue posible usar esta capacidad en línea de una manera que me parece genial.
antes de
Después
fuente