void Main()
{
// Using Task.Delay.ContinueWith...
Task.Delay(1000).ContinueWith(t => DoSomething());
// ... vs async await. Note that I'm not awaiting the task here
DoSomethingAsync();
}
public void DoSomething()
{
"Doing Something...".Dump();
}
public async Task DoSomethingAsync()
{
await Task.Delay(1000);
"Doing Something...".Dump();
}
在阅读了这篇博文之后https://blogs.msdn.microsoft.com/pfxteam/2012/03/24/show-i-exposite-asynchronous-wrappers-for-synchronal-methods/,我认为第一个实现是“正确的”,因为“doSomethingAsync()”实际上只是将方法卸载到threadpool中,博文指出:
不应纯粹为了卸载而公开异步方法:使用同步方法的使用者可以通过使用专门用于异步使用同步方法的功能(例如task.run)轻松地获得这种好处。
但是,StackOverflow上的这个答案建议了第二种解决方案:
延迟然后执行任务
这两个实现之间有什么实际的区别吗?如果'Async Await'实现也是有效的(甚至更正确),应该如何处理返回的任务?我真的不想等待它,这是一个火灾和忘记的操作,但我也想处理任何可能引发的异常。
在第一个实现中,我知道我可以通过使用ContinueWith,onlyonFaulted来处理异常。
它们相似,但不完全相同。例如,在SynchronizationContext.Current
之前,Async
方法的继续将被调度到此同步上下文中,但ContinueWith
不会,而是在线程池线程上运行。尽管使用ContinueWith
的另一个重载,但您可以使其执行相同的操作:
.ContinueWith(t => DoSomething(), TaskScheduler.FromCurrentSynchronizationContext());
您可以使用await yourtask.configureawait(false)
阻止在异步版本中对同步上下文进行调度。
那么,异常处理就不同了。在Async
版本中,exception将直接引发,如果有多个异常(例如fromawait task.whenall
)将只引发第一个异常,其余的将被吞掉。很难错过这个例外。
在ContinueWith
版本中,抛出的异常由T.exception
表示,并且它始终是AggregateException
,因此必须将其展开。另一方面-所有异常都在那里(如果有多个),并且没有一个被吞掉。但是,很容易忘记处理该异常。例如,在您的问题中的代码中,您不在continueWith
中处理exception,因此doSomething()
continuation无论如何都会执行,无论是否有异常。在Async
中,出现异常时不执行版本延续。
这两个实现都是“有效的”。您不应该忘记在这两种情况下处理异常。使用continuewith
-要么总是检查t.exception
,要么计划单独使用onlyonfaulted
继续(并且只在那里检查)。如果Async
版本包装正文位于try-catch
块中。由于火灾和遗忘的性质--你不能在调用站点处理异常,但你不应该完全放弃它们。
在短延迟后执行方法的具体情况中,我认为这只是偏好的问题(除了捕获同步上下文的差异)。我个人更喜欢continueWith
,它表达的意图更清楚,您不需要语义不清晰的单独方法。
问题内容: 在此示例中: 无法编译为: 而被编译器接受。 这个答案说明唯一的区别是,与不同,它允许您稍后引用类型,似乎并非如此。 是什么区别,并在这种情况下,为什么不第一编译? 问题答案: 通过使用以下签名定义方法: 并像这样调用它: 在jls§8.1.2中,我们发现(有趣的部分被我加粗了): 通用类声明定义了一组参数化类型(第4.5节), 每种可能通过类型arguments调用类型参数节的类型
问题内容: 今天,我按照一些说明在Linux中安装软件。有一个脚本需要首先运行。它设置一些环境变量。 指令告诉我要执行,但是我执行错误了。因此未设置环境。最后,我注意到了这一点并继续进行。 我想知道这两种调用脚本方法的区别。我对Linux完全陌生,所以请尽可能详细。 问题答案: 运行脚本,将启动一个新的运行脚本的外壳。新的外壳程序不会影响启动脚本的父外壳程序。 是的简写形式,它将在当前shell中
问题内容: 我刚开始使用Spring。我遇到了很多教程。我看到使用更多的例子比。我查看了Spring文档,但无法弄清楚使用其中一个的好处。有人可以提供一些解释吗? 问题答案: 是的便捷子类。 JavaDoc描述了一些添加的属性,这些属性在某些情况下可能有用: UrlBasedViewResolver的便利子类,它支持InternalResourceView(即Servlet和JSP)以及诸如Jst
问题内容: 我刚刚看到了包含标签的CSS代码。我看着MDN看看是什么,但我真的不明白。 有人可以解释它是如何工作的吗? 它会在我们通过CSS选择之前创建DOM元素吗? 问题答案: 根据这些文档,它们是等效的: 唯一的区别是CSS3中使用了双冒号,而单冒号是旧版本。 推理: CSS 3中引入了:: before表示法,以便在伪类和伪元素之间建立区别。浏览器还接受:在CSS 2中引入的表示法。
问题内容: 以下哪个更好? 要么 我知道的唯一区别是,当“ a”为null时,第一个返回false,而第二个抛出异常。除此之外,它们是否总是给出相同的结果? 问题答案: 使用时,你需要B在编译时知道类。使用时可以是动态的,并且可以在运行时更改。
问题内容: 根据MDN: 在许多情况下,revert关键字的工作原理与未设置的关键字完全相同。唯一的区别是属性具有由浏览器或用户创建的自定义样式表(在浏览器侧设置)设置的值。 我不了解浏览器和自定义样式表。浏览器和自定义样式表也都可以替换,对吗? 问题答案: 从MDN: 如果未设置CSS关键字从其父级继承,则将其重置为继承的属性,如果不是,则将其重置为初始值。换句话说,在第一种情况下,其行为类似于