Domanda

Qualcuno può spiegare quale sia la funzione await fa?

È stato utile?

Soluzione

parlato di questo al PDC ieri!

Await viene utilizzato in combinazione con Attività (programmazione parallela) in NET. E 'un essere parola chiave introdotta nella prossima versione di .NET. E 'più o meno consente di "mettere in pausa" l'esecuzione di un metodo per attendere il compito di completa esecuzione. Ecco un breve esempio:

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

Altri suggerimenti

In sostanza, i async e await parole chiave consentono di specificare che l'esecuzione di un metodo dovrebbe fermarsi a tutti gli utilizzi di await, che segnano chiamate di metodo asincrono, per poi riprendere una volta che l'operazione asincrona è stata completata. Questo consente di chiamare un metodo in thread principale di un'applicazione e gestire lavoro complesso in modo asincrono, senza la necessità di definire in modo esplicito le discussioni e si unisce o bloccare thread principale dell'app.

Pensate a come essere in qualche modo simile a una dichiarazione yield return in un metodo che produce un IEnumerable. Quando il tempo di esecuzione colpisce il yield, che sarà essenzialmente salvare lo stato attuale del metodo, e restituire il valore o di riferimento essendo ceduto. La volta successiva IEnumerator.MoveNext () viene chiamato sull'oggetto ritorno (che viene generato internamente dal runtime), vecchio stato del metodo viene ripristinato nello stack e l'esecuzione continua con la riga successiva dopo il yield return come se avessimo mai lasciato il metodo. Senza questa parola chiave, un tipo di IEnumerator deve essere personalizzato definito allo stato immagazzinare e manipolare le richieste di iterazione, con i metodi che possono diventare davvero molto complesso.

Analogamente, un metodo contrassegnato come async deve avere almeno un await. Su un await, il runtime salverà Stato e call stack del thread corrente, effettuare la chiamata asincrona, e torna rilassarsi al ciclo di messaggi del runtime per gestire il messaggio successivo e mantenere l'applicazione reattivo. Quando l'operazione asincrona è stata completata, alla prossima occasione di traffico, lo stack di chiamate per l'operazione asincrona viene spinto indietro e continuò come se la chiamata è sincrona.

Quindi, queste due nuove parole chiave fondamentalmente semplificare la codifica dei processi asincroni, molto simile yield return semplificato la generazione di enumerables personalizzati. Con un paio di parole chiave e un po 'di conoscenze di base, è possibile saltare tutti i dettagli confuso e spesso soggetti a errori di un modello tradizionale asincrono. Questo sarà prezioso per praticamente qualsiasi applicazione GUI event-driven come WinForms, WPF di Silverlight.

La risposta attualmente accettato è fuorviante. await non è in pausa nulla. Prima di tutto può essere utilizzato solo nei metodi o lambda segnato come async e tornando Task o void se non vi interessa avere esempio Task in esecuzione in questo metodo.

Ecco un esempio:

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

Output:

  

DoWork Inserito (). Dormire 3
  async compito iterazione 0
  lo stato delle attività: WaitingForActivation
  In attesa di ENTER
  async compito di iterazione 1
  async compito iterazione 2
  async compito iterazione 3
  async compito di iterazione 4
  async compito iterazione 5
  async compito iterazione 6
  async compito iterazione 7
  async compito iterazione 8
  async compito iterazione 9
  Uscendo DoWork ()

Per chiunque nuovi alla programmazione asincrona in .NET, ecco un (totalmente falso) analogia in uno scenario si può essere più familiarità con - chiamate AJAX utilizzando JavaScript / jQuery. Un semplice jQuery AJAX pubblicare aspetto:

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

Il motivo trattiamo i risultati in una funzione di richiamata è quindi non bloccare il thread corrente in attesa della chiamata AJAX al ritorno. Solo quando la risposta è pronta sarà get richiamata sparato, liberando il thread corrente per fare altre cose nel frattempo.

Ora, se JavaScript supportata la parola await (che ovviamente non è così ( ancora )), si potrebbe ottenere lo stesso con questo:

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

Questo è molto più pulito, ma sembra certo, come abbiamo introdotto sincrono, il blocco di codice. Ma il (finto) compilatore JavaScript avrebbe preso tutto dopo await e cablato in una richiamata, quindi in fase di esecuzione il secondo esempio si comporterebbe proprio come la prima.

Non può sembrare come ti sta risparmiando molto lavoro, ma quando si tratta di cose come i contesti di gestione delle eccezioni e sincronizzazione, il compilatore è in realtà facendo un molto di lavoro pesante per voi. Per di più, vi consiglio il domande frequenti seguito da serie di blog di Stephen Cleary .

Se dovessi per la sua attuazione in Java sarebbe sembrato qualche cosa in questo modo:

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

L'applicazione sarebbe usare in questo modo:

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");
        }
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top