Самый простой способ сделать огонь и забыть метод в C #?

Я видел в WCF у них [OperationContract(IsOneWay = true)] . Но WCF кажется медленным и тяжелым, чтобы создать неблокирующую функцию. В идеале было бы что-то вроде static void MethodFoo(){} , но я не думаю, что это существует.

Каков самый быстрый способ создания вызова неблокирующего метода в C #?

Например

 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 : Все, кто читает это, должны думать о том, хотят ли они, чтобы этот метод заканчивался. (См. Верхний ответ # 2). Если метод должен закончить, то в некоторых местах, например, в приложении ASP.NET, вам нужно будет что-то сделать, чтобы заблокировать и сохранить stream в живых. В противном случае это может привести к «огню-забыть-но-никогда-фактически-выполнить», и в этом случае, конечно, было бы проще вообще писать код. ( Хорошее описание того, как это работает в ASP.NET )

     ThreadPool.QueueUserWorkItem(o => FireAway()); 

    (пять лет спустя…)

     Task.Run(() => FireAway()); 

    как указано luisperezphd .

    Для C # 4.0 и новее мне кажется, что лучший ответ теперь дается здесь Аде Миллер: Самый простой способ сделать огонь и забыть метод в c # 4.0

     Task.Factory.StartNew(() => FireAway()); 

    Или даже…

     Task.Factory.StartNew(FireAway); 

    Или…

     new Task(FireAway).Start(); 

    Где FireAway

     public static void FireAway() { // Blah... } 

    Таким образом, благодаря терминологии classа и метода это превосходит версию threadpool от шести до девятнадцати символов в зависимости от того, который вы выбираете 🙂

     ThreadPool.QueueUserWorkItem(o => FireAway()); 

    Чтобы добавить к ответу Уилла , если это консольное приложение, просто WaitHandle и WaitHandle чтобы предотвратить его выход до завершения рабочего streamа:

     Using System; Using System.Threading; class Foo { static AutoResetEvent autoEvent = new AutoResetEvent(false); static void Main() { ThreadPoolQueueUserWorkItem(new WaitCallback(FireAway), autoEvent); autoEvent.WaitOne(); // Will wait for thread to complete } static void FireAway(object stateInfo) { System.Threading.Thread.Sleep(5000); Console.WriteLine("5 seconds later"); ((AutoResetEvent)stateInfo).Set(); } } 

    Для .NET 4.5:

     Task.Run(() => FireAway()); 

    Простым способом является создание и запуск streamа без параметрирования lambda:

     (new Thread(() => { FireAway(); MessageBox.Show("FireAway Finished!"); }) { Name = "Long Running Work Thread (FireAway Call)", Priority = ThreadPriority.BelowNormal }).Start(); 

    Используя этот метод над ThreadPool.QueueUserWorkItem, вы можете назвать свой новый stream, чтобы упростить его отладку. Кроме того, не забудьте использовать расширенную обработку ошибок в вашей программе, потому что любые необработанные исключения за пределами отладчика внезапно сбой вашего приложения:

    введите описание изображения здесь

    Рекомендуемый способ сделать это, когда вы используете Asp.Net и .Net 4.5.2, – это использовать QueueBackgroundWorkItem . Вот вспомогательный class:

     public static class BackgroundTaskRunner { public static void FireAndForgetTask(Action action) { HostingEnvironment.QueueBackgroundWorkItem(cancellationToken => // .Net 4.5.2 required { try { action(); } catch (Exception e) { // TODO: handle exception } }); } ///  /// Using async ///  public static void FireAndForgetTask(Func action) { HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken => // .Net 4.5.2 required { try { await action(); } catch (Exception e) { // TODO: handle exception } }); } } 

    Пример использования:

     BackgroundTaskRunner.FireAndForgetTask(() => { FireAway(); }); 

    или используя async:

     BackgroundTaskRunner.FireAndForgetTask(async () => { await FireAway(); }); 

    Это отлично работает на веб-сайтах Azure.

    Ссылки: Использование QueueBackgroundWorkItem для планирования фоновых заданий из приложения ASP.NET в .NET 4.5.2

    Вызов beginInvoke и не catching EndInvoke не является хорошим подходом. Ответ прост: причина, по которой вы должны вызвать EndInvoke, состоит в том, что результаты вызова (даже если нет возвращаемого значения) должны быть кэшированы .NET до тех пор, пока не будет вызван EndInvoke. Например, если вызываемый код генерирует исключение, исключение кэшируется в данных вызова. Пока вы не назовете EndInvoke, он останется в памяти. После вызова EndInvoke можно освободить память. В этом конкретном случае возможно, что память останется до тех пор, пока процесс не завершится, потому что данные поддерживаются внутренним кодом вызова. Я думаю, GC может в конечном итоге собрать его, но я не знаю, как GC узнает, что вы отказались от данных, а просто занимаете очень много времени, чтобы получить его. Я сомневаюсь, что это так. Следовательно, может произойти утечка памяти.

    Более подробную информацию можно найти на http://haacked.com/archive/2009/01/09/asynchronous-fire-and-forget-with-lambdas.aspx

    Простейший подход .NET 2.0 и более поздних версий – использование модели Asynchnonous Programming (т.е. BeginInvoke для делегата):

     static void Main(string[] args) { new MethodInvoker(FireAway).BeginInvoke(null, null); Console.WriteLine("Main: " + Thread.CurrentThread.ManagedThreadId); Thread.Sleep(5000); } private static void FireAway() { Thread.Sleep(2000); Console.WriteLine("FireAway: " + Thread.CurrentThread.ManagedThreadId ); } 

    Почти 10 лет спустя:

     Task.Run(FireAway); 

    Я бы добавил обработку исключений и запись в FireAway

    Давайте будем гением компьютера.