Pegue o método System.Windows.Forms.Control.Invoke (método Delegate)
Por que isso gera um erro de tempo de compilação:
string str = "woop";
Invoke(() => this.Text = str);
// Error: Cannot convert lambda expression to type 'System.Delegate'
// because it is not a delegate type
No entanto, isso funciona bem:
string str = "woop";
Invoke((Action)(() => this.Text = str));
Quando o método espera um delegado simples?
Invoke(()=>DoStuff)
e ainda recebi o erro. O problema era que eu usei o implícito 'this'. Para fazê-lo funcionar a partir de um membro de controle que você tem que ser explícito:this.Invoke(()=>DoStuff)
.Cansado de lançar lambdas repetidamente?
fonte
Lambda<T>
classe tem um método de conversão de identidade chamadoCast
, que retorna o que foi passado (Func<T, T>
). Agora oLambda<T>
é declarado, oLambda<Func<int, string>>
que significa que se você passar um métodoFunc<int, string>
paraCast
, ele retornaráFunc<int, string>
, poisT
nesse caso éFunc<int, string>
.Nove décimos das vezes as pessoas conseguem isso porque estão tentando empacotar no thread da interface do usuário. Aqui está o caminho preguiçoso:
Agora que foi digitado, o problema desaparece (resposta de qv Skeet) e temos esta sintaxe muito sucinta:
Para pontos de bônus, aqui está outra dica. Você não faria isso para as coisas da interface do usuário, mas nos casos em que você precisa que o SomeMethod bloqueie até que seja concluído (por exemplo, E / S de solicitação / resposta, aguardando a resposta), use um WaitHandle (qv msdn WaitAll, WaitAny, WaitOne).
Observe que AutoResetEvent é um derivado de WaitHandle.
E uma dica final, porque as coisas podem ficar confusas: WaitHandles interrompe o processo. Isto é o que eles deveriam fazer. Se você tentar empacotar no encadeamento da interface do usuário enquanto o interromper , seu aplicativo será interrompido . Nesse caso (a) alguma refatoração séria está em ordem e (b) como um corte temporário, você pode esperar assim:
fonte
System.Windows.Threading.Dispatcher.CurrentDispatcher
retornará o distribuidor do encadeamento CURRENT - ou seja, se você chamar esse método a partir de um encadeamento que não seja o encadeamento da interface do usuário, o código não será executado no encadeamento da interface do usuário.Peter Wone. você é homem. Levando um pouco mais o seu conceito, criei essas duas funções.
Coloco essas duas funções no meu aplicativo Formulário e posso fazer chamadas de trabalhadores em segundo plano como este
Talvez um pouco preguiçoso, mas não preciso configurar funções executadas pelo trabalhador, o que é super útil em casos como este
Essencialmente, obtenha alguns endereços IP de um gui DataGridView, faça ping neles, defina os ícones resultantes para verde ou vermelho e reative os botões no formulário. Sim, é um "paralelo.para" em um trabalhador em segundo plano. Sim, é muita sobrecarga de chamada, mas é insignificante para listas curtas e código muito mais compacto.
fonte
Tentei construir isso com base na resposta de @Andrey Naumov . Pode ser que isso seja uma ligeira melhora.
Onde type parameter
S
é o parâmetro formal (o parâmetro de entrada, que é mínimo necessário para inferir o restante dos tipos). Agora você pode chamar assim:Você pode ter sobrecargas adicionais para
Action<S>
e daExpression<Action<S>>
mesma forma na mesma classe. Por outro construído em tipos de delegado e de expressão, você terá que escrever classes separadas comoLambda
,Lambda<S, T>
,Lambda<S, T, U>
etc.Vantagem disso eu vejo sobre a abordagem original:
Uma especificação de tipo a menos (somente o parâmetro formal precisa ser especificado).
O que lhe dá a liberdade de usá-lo contra qualquer um
Func<int, T>
, não apenas quandoT
é ditostring
, como mostra os exemplos.Suporta expressões imediatamente. Na abordagem anterior, você precisará especificar tipos novamente, como:
para expressões.
Estender a classe para outros tipos de delegados (e expressões) é igualmente complicado como acima.
Na minha abordagem, você deve declarar tipos apenas uma vez (menos um para
Func
s).Outra maneira de implementar a resposta de Andrey é como não ser totalmente genérico
Então, as coisas se reduzem a:
Isso é ainda menos digitado, mas você perde certo tipo de segurança e , imo, isso não vale a pena.
fonte
Um pouco atrasado para a festa, mas você também pode transmitir assim
fonte
fonte
Jogando com XUnit e Fluent Assertions , foi possível usar esse recurso embutido de uma maneira que eu acho muito legal.
Antes
Depois de
fonte