Eu vi no WCF eles terem o [OperationContract(IsOneWay = true)]
atributo Mas o WCF parece meio lento e pesado, apenas para criar uma função sem bloqueio. Idealmente, haveria algo como non-blocking estático MethodFoo(){}
, mas acho que não existe.
Qual é a maneira mais rápida de criar uma chamada de método sem bloqueio em C #?
Por exemplo
class Foo
{
static void Main()
{
FireAway(); //No callback, just go away
Console.WriteLine("Happens immediately");
}
static void FireAway()
{
System.Threading.Thread.Sleep(5000);
Console.WriteLine("5 seconds later");
}
}
NB : Todo mundo que lê isso deve pensar se realmente deseja que o método termine. (Consulte a segunda resposta principal) Se o método precisar terminar, em alguns lugares, como um aplicativo ASP.NET, você precisará fazer algo para bloquear e manter o thread ativo. Caso contrário, isso poderia levar a "ignorar, mas nunca executar de fato"; nesse caso, é claro, seria mais simples escrever nenhum código. ( Uma boa descrição de como isso funciona no ASP.NET )
fonte
(new Action(FireAway)).BeginInvoke()
Task.Factory.StartNew(() => myevent());
de resposta stackoverflow.com/questions/14858261/…Para C # 4.0 e mais recente, parece-me que a melhor resposta agora é dada aqui por Ade Miller: Maneira mais simples de disparar e esquecer o método no c # 4.0
fonte
FireAway
?Task.Factory.StartNew(() => FireAway(foo));
.Task.Factory.StartNew(() => FireAway(foo));
foo não pode ser modificado em malha, como explicado aqui e aquiPara o .NET 4.5:
fonte
Task.Factory.StartNew(() => FireAway(), CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
acordo com blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspxPara adicionar à resposta de Will , se esse for um aplicativo de console, basta inserir um
AutoResetEvent
e aWaitHandle
para impedir que ele saia antes que o segmento de trabalho seja concluído:fonte
WaitOne
é sempre o bloqueio eAutoResetEvent
será sempre trabalhoWaitHandle
s, cada uma com a suaAutoResetEvent
e uma correspondenteThreadPool.QueueUserWorkItem
. Depois disso apenasWaitHandle.WaitAll(arrayOfWaitHandles)
.Uma maneira fácil é criar e iniciar um encadeamento com lambda sem parâmetros:
Usando esse método em ThreadPool.QueueUserWorkItem, você pode nomear seu novo thread para facilitar a depuração. Além disso, não se esqueça de usar o tratamento extensivo de erros em sua rotina, pois quaisquer exceções não tratadas fora de um depurador causam um travamento abrupto no aplicativo:
fonte
A maneira recomendada de fazer isso quando você estiver usando Asp.Net e .Net 4.5.2 é usando
QueueBackgroundWorkItem
. Aqui está uma classe auxiliar:Exemplo de uso:
ou usando assíncrono:
Isso funciona muito bem nos sites da Azure.
Referência: Usando QueueBackgroundWorkItem para agendar trabalhos em segundo plano de um aplicativo ASP.NET no .NET 4.5.2
fonte
Chamar beginInvoke e não capturar EndInvoke não é uma boa abordagem. A resposta é simples: o motivo pelo qual você deve chamar EndInvoke é porque os resultados da chamada (mesmo se não houver valor de retorno) devem ser armazenados em cache pelo .NET até que EndInvoke seja chamado. Por exemplo, se o código chamado lança uma exceção, a exceção é armazenada em cache nos dados de chamada. Até você chamar EndInvoke, ele permanece na memória. Depois de ligar para o EndInvoke, a memória pode ser liberada. Nesse caso específico, é possível que a memória permaneça até que o processo seja encerrado porque os dados são mantidos internamente pelo código de chamada. Eu acho que o GC pode eventualmente coletá-lo, mas não sei como o GC saberia que você abandonou os dados vs. apenas demorou muito tempo para recuperá-lo. Duvido que sim. Portanto, um vazamento de memória pode ocorrer.
Mais informações podem ser encontradas em http://haacked.com/archive/2009/01/09/asynchronous-fire-and-forget-with-lambdas.aspx
fonte
BeginInvoke
retornar um objeto wrapper que mantém uma referência ao objeto que contém os dados reais do resultado, mas não é referenciado, o objeto wrapper se tornará elegível para finalização assim que todas as referências a ele forem abandonadas.Quase 10 anos depois:
Eu adicionaria manipulação e registro de exceções no FireAway
fonte
A abordagem mais simples do .NET 2.0 e posterior é usar o Modelo de programação assíncrona (ou seja, BeginInvoke em um delegado):
fonte
Task.Run()
existir, essa era provavelmente a maneira mais concisa de fazer isso.