我有以下代码:
static async Task Callee()
{
await Task.Delay(1000);
}
static async Task Caller()
{
Callee(); // #1 fire and forget
await Callee(); // #2 >1s
Task.Run(() => Callee()); // #3 fire and forget
await Task.Run(() => Callee()); // #4 >1s
Task.Run(async () => await Callee()); // #5 fire and forget
await Task.Run(async () => await Callee()); // #6 >1s
}
static void Main(string[] args)
{
var stopWatch = new Stopwatch();
stopWatch.Start();
Caller().Wait();
stopWatch.Stop();
Console.WriteLine($"Elapsed: {stopWatch.ElapsedMilliseconds}");
Console.ReadKey();
}
#1以最简单的方式点燃和忘记。 #2只是等待。有趣的东西从#3开始。什么是电话背后的深度逻辑?
我已经意识到使用了火,并且忘记了ASP.NET中的警告here。我之所以这样问,是因为我们正在将我们的应用转移到我们无法再使用HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken => await LongMethodAsync());
的服务架构,而建议只需将其替换为Task.Run
。
我看到Task.Run运行一个新线程,那么#3和#5之间会有什么区别呢?
答案 0 :(得分:7)
我问这个问题,因为我们正在将我们的应用程序移动到服务结构中,我们再也无法使用HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken => await LongMethodAsync());建议只需用Task.Run替换它。
这是一个糟糕的建议。您应该使用separate background process separated from your web frontend by a queue。
电话背后的深度逻辑是什么?
答案 1 :(得分:2)
“26。”火与忘记“很好,只要你从未忘记过。” Maxim 26
如果你做任何火灾和忘记的情况,你有吞咽异常的巨大风险。吞下任何例外 - 但特别是致命的例外 - 是异常处理的致命罪。你最终得到的是内存中的程序,它将产生更难以理解和可重现的异常。所以不要开始。这是关于母校的两篇很好的文章:
http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx http://www.codeproject.com/Articles/9538/Exception-Handling-Best-Practices-in-NET
Full on Threads众所周知能够吞咽异常。事实上,你必须做的工作是不要吞下它们,然后检查它们是否在它们完成后有一个。您应该至少有一些后续任务可以记录(和可能的暴露)异常。或者你会真的后悔“火与忘记”。
希望有所帮助。