Frage

Kann mir jemand erklären, was die await Funktion hat?

War es hilfreich?

Lösung

Sie nur sprach darüber bei PDC gestern!

Await wird in Verbindung mit Aufgaben (parallele Programmierung) in .NET verwendet. Es ist ein Schlüsselwort Wesen in der nächsten Version von .NET eingeführt. Es ist mehr oder weniger können Sie „Pause“ die Durchführung eines Verfahrens zur vollständigen Ausführung der Aufgabe zu warten. Hier ist ein kurzes Beispiel:

//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();

Andere Tipps

Grundsätzlich sind die async und await Schlüsselwörter ermöglichen es Ihnen, dass die Ausführung eines Verfahrens angeben sollten auf allen Verwendungen von await zu stoppen, die asynchrone Methodenaufrufe zu markieren, und dann wieder auf, sobald die asynchrone Operation abgeschlossen ist. Auf diese Weise können Sie in einer App Haupt-Thread eine Methode aufrufen und verarbeiten asynchron komplexe Arbeit, ohne die Notwendigkeit, explizit Themen definieren und beitritt oder der App-Haupt-Thread blockiert wird.

Betrachten Sie es als etwas ähnlich einer yield return Anweisung in einem Verfahren ist ein IEnumerable zu erzeugen. Wenn die Laufzeit der yield trifft, wird es im Grunde des aktuellen Zustand des Verfahrens speichern, und gibt den Wert oder Referenz ergab werden. Das nächste Mal, IEnumerator.MoveNext () auf dem Rück Objekt aufgerufen wird (die durch die Laufzeit intern erzeugt wird), die alte Zustand der Methode wird auf den Stapel gestellt und die Ausführung fährt mit der nächsten Zeile nach dem yield return, als ob wir nie verlassen würden die Methode. Ohne dieses Schlüsselwort muss ein IEnumerator-Typ zu speichern Zustand individuell definiert werden und die Iteration Anfragen, mit Methoden behandeln, die in der Tat sehr komplex werden können.

In ähnlicher Weise ein Verfahren, wie async gekennzeichnet sind, müssen mindestens eine await haben. Auf einem await, wird die Laufzeit des aktuellen Threads und Call-Stack-Zustand, macht den asynchronen Aufruf und Abwickelstation zurück zu der Nachrichtenschleife der Laufzeit der nächste Nachricht speichern und halten die app reaktions zu handhaben. Wenn der asynchrone Vorgang abgeschlossen ist, in der nächsten Planungs Gelegenheit, zu dem Call-Stack nach oben wird den Asynchron-Betrieb zurückgeschoben in und fortgesetzt, als ob der Anruf synchron war.

Also, diese beiden neuen Keywords im Grunde die Codierung von asynchronen Prozesse vereinfachen, ähnlich wie yield return die Erzeugung von benutzerdefinierten enumerables vereinfacht. Mit ein paar Schlüsselwörter und ein wenig Hintergrundwissen, können Sie alle verwirrend und oft fehleranfällige Details eines traditionellen asynchronen Muster überspringen. Dies wird in so ziemlich jede ereignisgesteuerte GUI-Anwendung wie WinForms, WPF von Silverlight von unschätzbarem Wert sein.

Die derzeit akzeptierte Antwort ist irreführend. await pausiert nichts. Zunächst einmal kann es nur in Methoden oder Lambda-Ausdrücke gekennzeichnet als async und Rückkehr Task oder void verwendet werden, wenn Sie kümmern sich nicht Task Instanz mit dieser Methode ausgeführt wird.

Hier ist eine Darstellung:

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()");
    }
}

Ausgabe:

  

Eingetragen DoWork (). Schlafen 3
  async Aufgabe Iteration 0
  Aufgabenstatus: WaitingForActivation
  Warten auf ENTER
  async Aufgabe Iteration 1 |   async Aufgabe Iteration 2
  async Aufgabe Iteration 3
  async Aufgabe Iteration 4
  async Aufgabe Iteration 5
  async Aufgabe Iteration 6
  async Aufgabe Iteration 7
  async Aufgabe Iteration 8
  async Aufgabe Iteration 9
  Verlassen DoWork ()

Für jeden neu in der asynchronen Programmierung in .NET, hier ist eine (völlig fake) Analogie in einem Szenario, das Sie mit mehr vertraut sind - AJAX-Aufrufe JavaScript / jQuery verwenden. Eine einfache jQuery AJAX Post sieht wie folgt aus:

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

Der Grund, warum wir die Ergebnisse in einer Callback-Funktion zu verarbeiten ist, so dass wir den aktuellen Thread nicht blockieren, während für den AJAX-Aufruf zu Rückkehr zu warten. Erst wenn die Antwort bereit ist, wird der Rückruf get gefeuert, den aktuellen Thread zu befreien andere Dinge in der Zwischenzeit zu tun.

Nun, wenn JavaScript, um das await Schlüsselwort unterstützt (was es natürlich nicht ( noch )), können Sie das gleiche mit diesem erreichen können:

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

Das ist viel sauberer, aber es sieht aus wie sicher wir eingeführt synchron, Sperrung Code. Aber der (falschen) JavaScript-Compiler alles nach await gedauert hätte und verdrahtet sie in einen Rückruf, so zur Laufzeit das zweite Beispiel würde verhalten sich wie die erste.

Es kann nicht scheinen, wie es Ihnen viel Arbeit zu speichern, aber wenn es um Dinge wie die Ausnahmebehandlung und Synchronisation Kontexten kommt, wird der Compiler tatsächlich eine viel zu tun von schweres Heben für Sie. Für mehr, würde ich empfehlen die FAQs gefolgt von Stephen Cleary Blog Serie .

Wenn ich es in Java zu implementieren hätte es etwas, was wie folgt aussehen:

/**
 * @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();
}

Ihre Anwendung wäre es wie folgt verwenden:

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");
        }
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top