Mat*_*tin 134 .net c# nonblocking
我在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");
}
}
Run Code Online (Sandbox Code Playgroud)
注意:阅读此内容的每个人都应该考虑他们是否真的想要完成这个方法.(参见#2最佳答案)如果方法必须完成,那么在某些地方,比如ASP.NET应用程序,你需要做一些事情来阻止并保持线程活着.否则,这可能会导致"忘记但永远不会实际执行",在这种情况下,当然,根本不编写任何代码会更简单.(很好地描述了它在ASP.NET中的工作原理)
小智 254
ThreadPool.QueueUserWorkItem(o => FireAway());
Run Code Online (Sandbox Code Playgroud)
(五年后...)
Task.Run(() => FireAway());
Run Code Online (Sandbox Code Playgroud)
正如luisperezphd所指出的那样.
Pat*_*ski 38
对于C#4.0及更新版本,让我觉得Ade Miller现在给出了最好的答案:在c#4.0中做一个火灾和遗忘方法的最简单方法
Run Code Online (Sandbox Code Playgroud)Task.Factory.StartNew(() => FireAway());甚至...
Run Code Online (Sandbox Code Playgroud)Task.Factory.StartNew(FireAway);要么...
Run Code Online (Sandbox Code Playgroud)new Task(FireAway).Start();哪里
FireAway是Run Code Online (Sandbox Code Playgroud)public static void FireAway() { // Blah... }因此,凭借类和方法名称的简洁性,这取决于您选择的那个,使得线程池版本超过6到19个字符:)
Run Code Online (Sandbox Code Playgroud)ThreadPool.QueueUserWorkItem(o => FireAway());
Kev*_*Kev 17
要添加到Will的答案,如果这是一个控制台应用程序,只需在工作线程完成之前输入AutoResetEventa和a WaitHandle以防止它退出:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
Dav*_*och 17
对于.NET 4.5:
Task.Run(() => FireAway());
Run Code Online (Sandbox Code Playgroud)
Rob*_*les 15
一种简单的方法是使用无参数lambda创建和启动一个线程:
(new Thread(() => {
FireAway();
MessageBox.Show("FireAway Finished!");
}) {
Name = "Long Running Work Thread (FireAway Call)",
Priority = ThreadPriority.BelowNormal
}).Start();
Run Code Online (Sandbox Code Playgroud)
通过在ThreadPool.QueueUserWorkItem上使用此方法,您可以命名新线程以便于调试.另外,不要忘记在例程中使用大量的错误处理,因为调试器之外的任何未处理的异常都会突然崩溃您的应用程序:
Aug*_*eto 10
使用Asp.Net和.Net 4.5.2时,建议的方法是使用QueueBackgroundWorkItem.这是一个帮助类:
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
}
});
}
/// <summary>
/// Using async
/// </summary>
public static void FireAndForgetTask(Func<Task> action)
{
HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken => // .Net 4.5.2 required
{
try
{
await action();
}
catch (Exception e)
{
// TODO: handle exception
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
BackgroundTaskRunner.FireAndForgetTask(() =>
{
FireAway();
});
Run Code Online (Sandbox Code Playgroud)
或使用异步:
BackgroundTaskRunner.FireAndForgetTask(async () =>
{
await FireAway();
});
Run Code Online (Sandbox Code Playgroud)
这在Azure网站上很有用.
参考:使用QueueBackgroundWorkItem从.NET 4.5.2中的ASP.NET应用程序调度后台作业
小智 7
调用beginInvoke而不是捕获EndInvoke不是一个好方法.答案很简单:你应该调用EndInvoke的原因是因为在调用EndInvoke之前,.NET必须缓存调用的结果(即使没有返回值).例如,如果调用的代码抛出异常,则异常将缓存在调用数据中.在调用EndInvoke之前,它会保留在内存中.调用EndInvoke后,可以释放内存.对于这种特殊情况,内存可能会保留,直到进程关闭,因为数据是由调用代码在内部维护的.我想GC最终可能会收集它,但我不知道GC如何知道你已经放弃了数据而只是花了很长时间来检索它.我怀疑它确实如此.因此可能发生内存泄漏.
更多信息可以在http://haacked.com/archive/2009/01/09/asynchronous-fire-and-forget-with-lambdas.aspx找到
最简单的 .NET 2.0 及更高版本方法是使用异步编程模型(即委托上的 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 );
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
76198 次 |
| 最近记录: |