C#有一个很酷的新功能
public Task<string> async f()
{
string r = LongCompute();
return r;
}
但不等同于
public Future<String> f() {
return Globals.executorService.submit(new Callable<String>() {
public String call() throws Exception {
String r = longCompute();
return r;
}
});
}
在Java中,您可以更灵活地选择运行任务的线程池。
等待怎么样?它等同于只调用get
string s = await f();
就像
String s = f().get();
C#还有什么,或者它确实只是Java版本的语法糖? (我不是C#guru,所以我可能会遗漏一些东西)。
答案 0 :(得分:28)
不,await
不就像调用get()
一样。它的相当。
当您在C#中使用await
表达式时,编译器会有效地创建一个延续,因此如果等待尚未完成,则该方法可以立即返回,并且仅在完成时继续处理。延续将在适当的上下文中运行 - 所以如果你在await
表达式之前的UI线程上,你将继续在UI线程上继续,但是在你等待的时候不会阻塞UI线程结果。例如:
public async void HandleButtonClick(object sender, EventArgs e)
{
// All of this method will run in the UI thread, which it needs
// to as it touches the UI... however, it won't block when it does
// the web operation.
string url = urlTextBox.Text;
WebClient client = new WebClient();
string webText = await client.DownloadStringTaskAsync(url);
// Continuation... automatically called in the UI thread, with appropriate
// context (local variables etc) which we used earlier.
sizeTextBox.Text = string.Format("{0}: {1}", url, webText.Length);
}
最终它是所有的语法糖,但很多比你所展示的糖更复杂。
网上已有很多详细信息。例如:
答案 1 :(得分:9)
Jon没有解释真实点。
Java ExecutorService
基于线程,而C#的await
可以说是基于光纤 >
两者都允许多任务处理,它在并发功能(即运行&#34;同时&#34;)之间分割计算资源。第一种多任务处理称为先发制人,而第二种合作。从历史上看,先发制人的多任务处理被认为更先进,更优于合作。实际上,在先发制人的多任务处理被消费者操作系统支持之前,计算机确实很糟糕。但是,抢先式多任务处理有其缺点。它可能很难编程,并且它会占用更多内存。
两者之间的主要区别在于抢占式多任务处理允许运行时(通常是操作系统本身)随时停止任何功能并启动不同的功能(并在不同的CPU上同时运行它们)。同时,协作式多任务处理需要运行功能结束或自动暂停。我们大多数人都熟悉多线程形式的抢占式多任务处理,以及随之而来的精心编程。很少有人熟悉合作多任务处理,现在通常称为光纤或协同程序(在这种情况下,它在抢占式操作系统的线程内的用户空间中实现)。
无论如何,重点是ExecutorService
和await
不能直接比较,await
通常不会超过真正的多线程(除了它的功能很好)句法糖)。包含await
(以及基于协作式多任务处理)的C#原因是平台上的主要GUI工具包不是为多线程而设计的,重构它们以支持并发性需要大量的工作。协作式多任务处理适用于UI,因为大多数事件处理程序都很短并且可以串行执行。 await
通过让长事件处理程序暂停并在渲染函数有机会运行后恢复来扩展事件循环的概念。所有这些都发生在单个CPU核心的单个线程中。
他们都认为共同点是他们是两种形式的多任务处理,Future.get
和await Task
都是同步形式。
正如可以预料的那样,C#并没有对线程和线程池的良好支持。同样,Java在许多库中包含光纤/协同例程/异步,例如Servlet 3.0和javafx.concurrent.Task
。
响应Jon Skeet: Continuation (因为调用光纤的用户态实现机制)是非常重要的,但线程的实现并不复杂。 Jon可能已被抛弃,因为线程背后的算法是在OS中,而不是在编译器或.NET运行时中。
答案 2 :(得分:4)
只是为了扩展正确的Jon Skeet的答案。
这不是C#等待表达式的Java模拟。 Hoverer,一些Java框架具有相同的功能:
实际上,它们会在运行中生成例程或状态机代码。