Estou procurando boas idéias para implementar uma maneira genérica de executar uma única linha (ou delegado anônimo) de código com um tempo limite.
TemperamentalClass tc = new TemperamentalClass();
tc.DoSomething(); // normally runs in 30 sec. Want to error at 1 min
Estou procurando uma solução que possa ser implementada de maneira elegante em muitos lugares onde meu código interage com um código temperamental (que não posso mudar).
Além disso, eu gostaria que o código de "tempo limite excedido" não fosse mais executado, se possível.
c#
multithreading
c#-3.0
asynchronous
timeout
chilltemp
fonte
fonte
Respostas:
A parte realmente complicada aqui foi acabar com a tarefa de longa execução, passando o thread do executor da Action de volta para um local em que pudesse ser abortado. Eu consegui isso com o uso de um delegado empacotado que distribui o thread para matar uma variável local no método que criou o lambda.
Eu envio este exemplo, para sua diversão. O método que você realmente está interessado é CallWithTimeout. Isso cancelará o encadeamento de execução longa, interrompendo-o e engolindo o ThreadAbortException :
Uso:
O método estático que está fazendo o trabalho:
fonte
Estamos usando um código como este fortemente na produção :
A implementação é de código aberto, funciona com eficiência mesmo em cenários de computação paralela e está disponível como parte das Bibliotecas Compartilhadas Lokad
Este código ainda está com erros, você pode tentar com este pequeno programa de teste:
Existe uma condição de corrida. É claramente possível que um ThreadAbortException seja gerado após o método
WaitFor<int>.Run()
ser chamado. Não encontrei uma maneira confiável de corrigir isso, no entanto, com o mesmo teste, não consigo reproduzir nenhum problema com a resposta aceita pelo TheSoftwareJedi .fonte
Bem, você pode fazer as coisas com os delegados (BeginInvoke, com um retorno de chamada configurando um sinalizador - e o código original aguardando esse sinalizador ou tempo limite) - mas o problema é que é muito difícil desligar o código em execução. Por exemplo, matar (ou pausar) um segmento é perigoso ... então eu não acho que exista uma maneira fácil de fazer isso com robustez.
Vou postar isso, mas observe que não é o ideal - ele não interrompe a tarefa de longa execução e não limpa adequadamente em caso de falha.
fonte
Algumas pequenas mudanças na grande resposta de Pop Catalin:
Sobrecargas foram adicionadas para dar suporte ao trabalhador de sinalização para cancelar a execução:
fonte
É assim que eu faria:
fonte
Eu acabei de nocautear agora, então pode precisar de algumas melhorias, mas fará o que você quiser. É um aplicativo de console simples, mas demonstra os princípios necessários.
fonte
Que tal usar o Thread.Join (int timeout)?
fonte