Я видел в WCF у них есть [OperationContract(IsOneWay = true)]
атрибут. Но WCF кажется медленным и тяжелым только для того, чтобы создать неблокирующую функцию. В идеале было бы что-то вроде статического неблокирования пустот 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, вам нужно будет что-то сделать, чтобы заблокировать и поддерживать поток живым. В противном случае это может привести к «запуску, но никогда не выполнению», и в этом случае, конечно, было бы проще вообще не писать код. ( Хорошее описание того, как это работает в ASP.NET )
источник
(new Action(FireAway)).BeginInvoke()
Task.Factory.StartNew(() => myevent());
из ответа stackoverflow.com/questions/14858261/…Для C # 4.0 и новее мне кажется, что лучший ответ теперь дает здесь Ade Miller: Самый простой способ создать метод «забыл и забыл» в c # 4.0
источник
FireAway
?Task.Factory.StartNew(() => FireAway(foo));
.Task.Factory.StartNew(() => FireAway(foo));
foo не может быть изменено в цикле, как объяснено здесь и здесьДля .NET 4.5:
источник
Task.Factory.StartNew(() => FireAway(), CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
К вашему сведениюЧтобы добавить к ответу Уилла , если это консольное приложение, просто добавьте
AutoResetEvent
a и a,WaitHandle
чтобы предотвратить его выход до завершения рабочего потока:источник
WaitOne
всегда блокирует иAutoResetEvent
всегда будет работатьWaitHandle
s, каждый со своимAutoResetEvent
и своимThreadPool.QueueUserWorkItem
. После этого как разWaitHandle.WaitAll(arrayOfWaitHandles)
.Самый простой способ - создать и запустить поток с лямбда без параметров:
Используя этот метод поверх ThreadPool.QueueUserWorkItem, вы можете назвать новый поток, чтобы облегчить его отладку. Кроме того, не забывайте использовать расширенную обработку ошибок в своей процедуре, потому что любые необработанные исключения вне отладчика будут внезапно вызывать сбой вашего приложения:
источник
Рекомендуемый способ сделать это, когда вы используете Asp.Net и .Net 4.5.2, это использовать
QueueBackgroundWorkItem
. Вот вспомогательный класс:Пример использования:
или используя async:
Это прекрасно работает на веб-сайтах Azure.
Ссылка: Использование QueueBackgroundWorkItem для планирования фоновых заданий из приложения ASP.NET в .NET 4.5.2
источник
Вызов beginInvoke и отсутствие перехвата EndInvoke не очень хороший подход. Ответ прост: причина, по которой вы должны вызывать EndInvoke, заключается в том, что результаты вызова (даже если нет возвращаемого значения) должны кэшироваться .NET до вызова EndInvoke. Например, если вызванный код генерирует исключение, то исключение кэшируется в данных вызова. Пока вы не вызовете EndInvoke, он останется в памяти. После вызова EndInvoke память может быть освобождена. В этом конкретном случае возможно, что память останется до тех пор, пока процесс не остановится, потому что данные поддерживаются внутренне кодом вызова. Я думаю, что GC может в конечном итоге собрать его, но я не знаю, как GC узнает, что вы отказались от данных, а просто потратили очень много времени на их получение. Я сомневаюсь, что это так. Следовательно, может произойти утечка памяти.
Больше можно найти на http://haacked.com/archive/2009/01/09/asynchronous-fire-and-forget-with-lambdas.aspx
источник
BeginInvoke
возвращает объект-обертку, который содержит ссылку, но не на которую ссылается объект, который содержит реальные данные результата, объект-обертка получит право на финализацию, как только все ссылки на него будут отменены.Почти 10 лет спустя:
Я бы добавил обработку исключений и ведение журнала внутри FireAway
источник
Простейшим подходом .NET 2.0 и более поздних версий является использование модели асинхронного программирования (т. Е. BeginInvoke для делегата):
источник
Task.Run()
этого это был, пожалуй, самый лаконичный способ сделать это.