什么是新的C#等待function?

任何人都可以解释什么await函数呢?

他们昨天刚刚在PDC上谈到这个 !

等待与.NET中的任务(并行编程)结合使用。 这是在下一个.NET版本中引入的关键字。 它或多或less的让你“暂停”一个方法的执行,等待任务完成执行。 这里有一个简单的例子:

 //create and run a new task Task<DataTable> dataTask = new Task<DataTable>(SomeCrazyDatabaseOperation); //run some other code immediately after this task is started and running ShowLoaderControl(); StartStoryboard(); //this will actually "pause" the code execution until the task completes. It doesn't lock the thread, but rather waits for the result, similar to an async callback // please so also note, that the task needs to be started before it can be awaited. Otherwise it will never return dataTask.Start(); DataTable table = await dataTask; //Now we can perform operations on the Task result, as if we're executing code after the async operation completed listBoxControl.DataContext = table; StopStoryboard(); HideLoaderControl(); 

基本上, asyncawait关键字允许你指定一个方法的执行应该在await所有用法上停止,这会标记asynchronous方法调用,然后在asynchronous操作完成后继续执行。 这允许您在应用程序的主线程中调用方法,并asynchronous处理复杂的工作,而无需显式定义线程和连接或阻止应用程序的主线程。

把它看作与产生IEnumerable的方法中的yield return语句有些类似。 当运行时命中yield ,它将基本上保存方法的当前状态,并返回正在生成的值或引用。 下一次在返回对象(由运行时在内部生成)上调用IEnumerator.MoveNext()时,方法的旧状态将恢复到堆栈,并在yield return后继续执行下一行,就好像我们永远不会离开了方法。 如果没有这个关键字,IEnumeratortypes必须被自定义来存储状态并处理迭代请求,其方法可能非常复杂。

同样,标记为async的方法必须至less有一个await 。 在await ,运行时会保存当前线程的状态和调用堆栈,进行asynchronous调用,然后退回到运行时的消息循环来处理下一条消息,并保持应用程序响应。 当asynchronous操作完成时,在下一个调度机会中,调用asynchronous操作的调用堆栈被推入并继续,就好像调用是同步的。

所以,这两个新的关键字基本上简化了asynchronous进程的编码,就像yield return简化了自定义枚举的生成一样。 有了几个关键字和一些背景知识,就可以跳过传统asynchronous模式中所有令人困惑且常常容易出错的细节。 这在几乎所有事件驱动的GUI应用程序(如Silverlight的Winforms,WPF)中都是INVALUABLE。

目前接受的答案是误导性的。 await不会暂停任何事情。 首先,它只能用于方法或标记为async lambdaexpression式,并且返回Taskvoid如果不关心在此方法中运行Task实例。

这是一个例子:

 internal class Program { private static void Main(string[] args) { var task = DoWork(); Console.WriteLine("Task status: " + task.Status); Console.WriteLine("Waiting for ENTER"); Console.ReadLine(); } private static async Task DoWork() { Console.WriteLine("Entered DoWork(). Sleeping 3"); // imitating time consuming code // in a real-world app this should be inside task, // so method returns fast Thread.Sleep(3000); await Task.Run(() => { for (int i = 0; i < 10; i++) { Console.WriteLine("async task iteration " + i); // imitating time consuming code Thread.Sleep(1000); } }); Console.WriteLine("Exiting DoWork()"); } } 

输出:

inputDoWork()。 睡3
asynchronous任务迭代0
任务状态:WaitingForActivation
等待ENTER
asynchronous任务迭代1
asynchronous任务迭代2
asynchronous任务迭代3
asynchronous任务迭代4
asynchronous任务迭代5
asynchronous任务迭代6
asynchronous任务迭代7
asynchronous任务迭代8
asynchronous任务迭代9
退出DoWork()

对于任何在.NET中进行asynchronous编程的人来说,下面是一个你可能更熟悉的场景(完全是假的)的比喻 – 使用JavaScript / jQuery的AJAX调用。 一个简单的jQuery AJAX文章看起来像这样:

 $.post(url, values, function(data) { // AJAX call completed, do something with returned data here }); 

我们在callback函数中处理结果的原因是我们在等待AJAX​​调用返回时不会阻塞当前线程。 只有当响应准备就绪时,callback才会被解除,同时释放当前的线程来做其他事情。

现在,如果JavaScript支持await关键字(当然它不( 但! )),你可以实现这一点:

 var data = await $.post(url, values); // AJAX call completed, do something with returned data here 

这是一个更清洁,但它确实看起来像我们引入同步,阻止代码。 但是(假的)JavaScript编译器在await并将其连接到一个callbackawait之后会采取所有的措施,所以在运行时第二个例子的行为就像第一个一样。

看起来好像不是在节省你大量的工作,但是当涉及exception处理和同步上下文等事情时,编译器实际上正在为你做很多繁重的工作。 更多的,我会推荐Stephen Cleary的博客系列的FAQ 。

如果我不得不在Java中实现它,它会看起来像这样:

 /** * @author Ilya Gazman */ public abstract class SynchronizedTask{ private ArrayList<Runnable> listeners = new ArrayList<Runnable>(); private static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(6, 6, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1000)); public final void await(Runnable listener){ synchronized (this) { listeners.add(listener); } } public void excecute(){ onExcecute(); for (int i = listeners.size() - 1; i >= 0; i--) { Runnable runnable; synchronized (this) { runnable = listeners.remove(i); } threadPoolExecutor.execute(runnable); } } protected abstract void onExcecute(); } 

你的应用程序会像这样使用它:

 public class Test{ private Job job = new Job(); public Test() { craeteSomeJobToRunInBackground(); methode1(); methode2(); } private void methode1(){ System.out.println("Running methode 1"); job.await(new Runnable() { @Override public void run() { System.out.println("Continue to running methode 1"); } }); } private void methode2(){ System.out.println("Running methode 2"); } private void craeteSomeJobToRunInBackground() { new Thread(new Runnable() { @Override public void run() { job.excecute(); } }).start(); } private class Job extends SynchronizedTask{ @Override protected void onExcecute() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Job is done"); } } }