题
任何人都可以解释什么 await
功能呢?
解决方案
他们只是谈到了这一点,在PDC 昨天!
等待以与在.NET任务(并行编程)结合使用。这是一个关键字正在.NET的下一个版本推出。这或多或少让你“暂停”的方法的执行等待任务完成执行。下面是一个简单的例子:
//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();
其他提示
基本上,async
和await
关键字允许你指定一个方法的执行应在await
的所有用途,这标志着异步方法调用停止,然后恢复一旦异步操作完成。这使您可以异步调用的方法在应用程序的主线程和处理复杂的工作,而无需显式定义主题,并加入或阻止应用程序的主线程。
把它看成是有点类似于一个yield return
语句生产一个IEnumerable的方法。当运行时击中yield
,它基本上会保存方法的当前状态,并返回所得到的值或引用。下一次IEnumerator.MoveNext()被调用返回的对象(这是由运行时内部产生的)上,该方法的老状态恢复到堆栈和执行与yield return
的下一行继续,如同我们从未离开方法。如果没有这个关键字,一个IEnumerator类型必须自定义的存储状态,并且处理迭代的请求,与方法,可以变得非常复杂确实
类似地,标记为async
的方法必须具有至少一个await
。在一个await
,运行时将保存当前线程的状态和调用堆栈,使异步调用,身心恢复运行的消息循环处理的下一条消息,并保持该应用程序响应。当异步操作完成时,在下一调度时机,调用堆栈向上到异步操作中被推回,并继续,就好像呼叫是同步的。
因此,这两个新的关键字基本上简化异步处理的编码,很像yield return
简化定制可枚举的产生。一对夫妇关键字和一点背景知识,你可以跳过传统的异步模式的所有混乱,往往容易出错的细节。这将是非常宝贵在非常喜欢的Winforms任何事件驱动GUI的应用程序,的Silverlight WPF。
目前公认的答案是误导。
await
没有暂停任何东西。
首先,它只能在标记为async
和返回Task
或void
方法或lambda表达式中使用,如果你不小心在有这种方法运行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()");
}
}
输出:
进入的DoWork()。睡3个结果 异步任务迭代0点击 任务状态:WaitingForActivation结果 等待ENTER结果 异步任务迭代1结果 异步任务迭代2结果 异步任务迭代3结果 异步任务迭代4点击 异步任务迭代5点击 异步任务迭代6点击 异步任务迭代7结果 异步任务迭代8次点击 异步任务迭代9点击 离开的DoWork()
对于任何新的异步编程。网,这是一(完全假)的比喻,在一个场景你可能更熟悉-阿贾克斯的电话使用JavaScript/!一个简单的jQuery阿贾克斯后看起来是这样的:
$.post(url, values, function(data) {
// AJAX call completed, do something with returned data here
});
我们之所以过程的结果在回呼功能是所以我们不阻止当前线,同时等待阿贾克斯呼吁的回报。只有当的响应已准备好将回调得到射击,释放前线去做其他的事情的平均时间。
现在,如果JavaScript支持 await
关键词(其当然,这并不(还没有!)),可以同样实现这一点:
var data = await $.post(url, values);
// AJAX call completed, do something with returned data here
这是一个很大的吸尘器,但它确实看起来我们介绍了同步,阻挡的代码。但是(假)JavaScript编译器,将采取一切之后 await
并且把它变成一个回调,这样在运行的第二次例会表现得就像第一次。
它可能看起来不像是你节省很多工作,但是当它涉及到的东西喜欢的例外处理和同步的情况下,编译器实际上是做一个 很多 的繁重你。欲了解更多,我会推荐的 常见问题解答 随后通过 斯蒂芬*克利里的博客串.
如果我必须实现它在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");
}
}
}