質問
誰でもできるので説明を await
機能しているか。
解決
かなり こう話でのPDC 昨日!
待と連動して使用することにより作業(並列プログラミング)です。います。このキーワードで導入され、次のバージョンです。います。でりき"一時停止"の実行方法を設定されている投稿のみ表示されます。簡単にストーリーをご紹介例
//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
, 、非同期メソッドが呼び出され、非同期操作が完了したら再開します。これにより、アプリのメインスレッドでメソッドを呼び出し、スレッドを明示的に定義してアプリのメインスレッドを結合またはブロックすることなく、複雑な作業を非同期に処理できます。
それはaに多少似ていると考えてください yield return
IENUMERABLEを生成するメソッドのステートメント。ランタイムがヒットしたとき yield
, 、基本的にメソッドの現在の状態を保存し、生成される値または参照を返します。次回IENUMERATOR.MOVENEXT()が戻りオブジェクトで呼び出されたとき(ランタイムまでに内部で生成される)、メソッドの古い状態がスタックに復元され、実行が次の行で継続されます。 yield return
方法を離れたことがないかのように。このキーワードがなければ、IENumeratorのタイプは、状態を保存して反復要求を処理するためにカスタム定義する必要があります。
同様に、としてマークされたメソッド async
少なくとも1つが必要です await
. 。で await
, 、ランタイムは現在のスレッドの状態を保存してスタックを呼び出し、非同期コールを行い、ランタイムのメッセージループに戻って次のメッセージを処理し、アプリに応答します。非同期操作が完了した場合、次のスケジューリングの機会に、非同期操作をアップするコールスタックが押し戻され、まるで呼び出しが同期しているかのように継続されます。
したがって、これらの2つの新しいキーワードは、基本的に非同期プロセスのコーディングを簡素化します。 yield return
カスタム列挙の生成を簡素化しました。いくつかのキーワードと少しの背景知識を使用すると、従来の非同期パターンの混乱とエラーが発生しやすい詳細をすべてスキップできます。これは、Winforms、WPFのシルバーライトのような、ほとんどすべてのイベント主導のGUIアプリで非常に貴重です。
現在受け入れられている答えは誤解を招きます。await
何も一時停止していません。まず第一に、それは、とマークされた方法またはラムダでのみ使用できます async
そして戻ってきます Task
また void
あなたが持っていることを気にしないなら 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
タスクステータス:Activationの待機
Enterを待っています
非同期タスク反復1
非同期タスク反復2
非同期タスク反復3
非同期タスク反復4
非同期タスク反復5
非同期タスク反復6
非同期タスク反復7
非同期タスク反復8
非同期タスク反復9
dowork()を終了する
.NETで非同期プログラミングを初めて使用する人の場合、これはあなたがよりよくよく知っているかもしれないシナリオの(完全に偽の)類推です-JavaScript/jQueryを使用してAjaxコール。シンプルなjquery ajaxの投稿は次のようになります:
$.post(url, values, function(data) {
// AJAX call completed, do something with returned data here
});
結果をコールバック関数で処理する理由は、Ajaxコールが返されるのを待っている間に現在のスレッドをブロックしないようにするためです。応答の準備ができた場合にのみ、コールバックが起動し、現在のスレッドを解放して、その間に他のことを行います。
さて、JavaScriptがサポートした場合 await
キーワード(もちろんそうではありません(まだ!)、あなたはこれで同じことを達成することができます:
var data = await $.post(url, values);
// AJAX call completed, do something with returned data here
それはかなりクリーンですが、同期、ブロッキングコードを導入したように見えます。しかし、(偽の)JavaScriptコンパイラはすべてを取ったでしょう await
そして、それをコールバックに配線したので、実行時に2番目の例は最初の例のように動作します。
それはあなたに多くの仕事を節約しているようには思えないかもしれませんが、例外処理や同期のコンテキストなどのことに関しては、コンパイラは実際に行っています 多く あなたのために重い持ち上げの。さらに、お勧めします FAQ に続く Stephen Clearyのブログシリーズ.
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");
}
}
}