Vi en WCF que tienen el [OperationContract(IsOneWay = true)]
atributo. Pero WCF parece un poco lento y pesado solo para crear una función sin bloqueo. Idealmente, habría algo como no bloqueo de vacío estático MethodFoo(){}
, pero no creo que exista.
¿Cuál es la forma más rápida de crear una llamada a un método sin bloqueo en C #?
P.ej
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 : Todos los que lean esto deberían pensar si realmente quieren que el método termine. (Consulte la respuesta principal n. ° 2) Si el método tiene que finalizar, en algunos lugares, como una aplicación ASP.NET, deberá hacer algo para bloquear y mantener vivo el hilo. De lo contrario, esto podría llevar a "disparar-olvidar-pero-nunca-realmente-ejecutar", en cuyo caso, por supuesto, sería más simple no escribir ningún código. ( Una buena descripción de cómo funciona esto en ASP.NET )
fuente
(new Action(FireAway)).BeginInvoke()
Task.Factory.StartNew(() => myevent());
de la respuesta stackoverflow.com/questions/14858261/…Para C # 4.0 y más reciente, me parece que la mejor respuesta ahora la da Ade Miller: la forma más sencilla de hacer fuego y olvidar el método en c # 4.0
fuente
FireAway
?Task.Factory.StartNew(() => FireAway(foo));
.Task.Factory.StartNew(() => FireAway(foo));
foo no se puede modificar en bucle como se explica aquí y aquíPara .NET 4.5:
fuente
Task.Factory.StartNew(() => FireAway(), CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
acuerdo con blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspxPara agregar a la respuesta de Will , si esta es una aplicación de consola, simplemente agregue una
AutoResetEvent
y unaWaitHandle
para evitar que salga antes de que se complete el subproceso de trabajo:fuente
WaitOne
siempre está bloqueando yAutoResetEvent
siempre funcionaráWaitHandle
s, cada uno con su propioAutoResetEvent
y un correspondienteThreadPool.QueueUserWorkItem
. Después de eso soloWaitHandle.WaitAll(arrayOfWaitHandles)
.Una manera fácil es crear e iniciar un hilo con lambda sin parámetros:
Al usar este método sobre ThreadPool.QueueUserWorkItem, puede nombrar su nuevo hilo para facilitar la depuración. Además, no olvide utilizar el manejo extensivo de errores en su rutina porque cualquier excepción no manejada fuera de un depurador bloqueará abruptamente su aplicación:
fuente
La forma recomendada de hacer esto cuando usa Asp.Net y .Net 4.5.2 es mediante
QueueBackgroundWorkItem
. Aquí hay una clase auxiliar:Ejemplo de uso:
o usando asíncrono:
Esto funciona muy bien en los sitios web de Azure.
Referencia: Uso de QueueBackgroundWorkItem para programar trabajos en segundo plano desde una aplicación ASP.NET en .NET 4.5.2
fuente
Llamar a beginInvoke y no capturar EndInvoke no es un buen enfoque. La respuesta es simple: la razón por la que debe llamar a EndInvoke es porque los resultados de la invocación (incluso si no hay un valor de retorno) deben ser almacenados en caché por .NET hasta que se llame a EndInvoke. Por ejemplo, si el código invocado genera una excepción, la excepción se almacena en caché en los datos de invocación. Hasta que llame a EndInvoke, permanece en la memoria. Después de llamar a EndInvoke, se puede liberar la memoria. Para este caso particular, es posible que la memoria permanezca hasta que el proceso se cierre porque el código de invocación mantiene internamente los datos. Supongo que el GC eventualmente podría recopilarlo, pero no sé cómo el GC sabría que has abandonado los datos en lugar de solo tomarte un tiempo realmente largo para recuperarlos. Dudo que lo haga. Por lo tanto, puede ocurrir una pérdida de memoria.
Se puede encontrar más en http://haacked.com/archive/2009/01/09/asynchronous-fire-and-forget-with-lambdas.aspx
fuente
BeginInvoke
devuelve un objeto contenedor que contiene una referencia, pero no es referenciado por, el objeto que contiene los datos del resultado real, el objeto contenedor será elegible para su finalización una vez que se abandonen todas las referencias a él.Casi 10 años después:
Agregaría manejo y registro de excepciones dentro de FireAway
fuente
El enfoque más simple de .NET 2.0 y posterior es utilizar el modelo de programación asinchnonous (es decir, BeginInvoke en un delegado):
fuente
Task.Run()
existir, esta era probablemente la forma más concisa de hacer esto.