Domanda

Per qualche motivo c'è una pausa dopo il programma di seguito ha inizio. Credo che WebClient().DownloadStringTaskAsync() è la causa.

class Program
{
    static void Main(string[] args)
    {
        AsyncReturnTask();

        for (int i = 0; i < 15; i++)
        {
            Console.WriteLine(i);
            Thread.Sleep(100);
        }
    }

    public static async void AsyncReturnTask()
    {
        var result = await DownloadAndReturnTaskStringAsync();
        Console.WriteLine(result);
    }

    private static async Task<string> DownloadAndReturnTaskStringAsync()
    {
        return await new WebClient().DownloadStringTaskAsync(new Uri("http://www.weather.gov"));
    }
}

Per quanto ho capito il mio programma dovrebbe iniziare immediatamente il conteggio da 0 a 15. Sto facendo qualcosa di sbagliato?

Ho avuto lo stesso problema con il campione originale Netflix download (che si ottiene con la CTP ) - dopo aver premuto il pulsante di ricerca dei primi blocca UI - e dopo qualche tempo è reattivo mentre loadning i prossimi film. E credo che non congelare nella presentazione di Anders Hejlsberg al PDC 2010.

Ancora una cosa. Quando invece di

return await new WebClient().DownloadStringTaskAsync(new Uri("http://www.weather.gov"));

Io uso il mio metodo:

return await ReturnOrdinaryTask();

Il che è:

public static Task<string> ReturnOrdinaryTask()
{
    var t = Task.Factory.StartNew(() =>
    {
        for (int i = 0; i < 10; i++)
        {
            Console.WriteLine("------------- " + i.ToString());
            Thread.Sleep(100);
        }
        return "some text";
    });
    return t;
}

E 'funziona come dovrebbe. Voglio dire che non carica niente, ma comincia immediatamente e non blocca il thread principale, mentre si fa il suo lavoro.

Modifica

OK, quello che io credo in questo momento è: la funzione WebClient.DownloadStringTaskAsync è avvitato. Dovrebbe funzionare senza il periodo di blocco iniziale, in questo modo:

    static void Main(string[] args)
    {
        WebClient cli = new WebClient();
        Task.Factory.StartNew(() =>
            {
                cli.DownloadStringCompleted += (sender, e) => Console.WriteLine(e.Result);
                cli.DownloadStringAsync(new Uri("http://www.weather.gov"));
            });

        for (int i = 0; i < 100; i++)
        {
            Console.WriteLine(i);
            Thread.Sleep(100);
        }
    }
È stato utile?

Soluzione

Mentre il programma fa blocco per un po ', lo fa riprendere l'esecuzione nel ciclo for, prima che il risultato viene restituito dal server remoto.

Ricordate che la nuova API asincrona è ancora single-threaded. Così WebClient().DownloadStringTaskAsync() ha ancora bisogno per funzionare sul vostro filo fino a quando la richiesta è stato preparato e inviato al server, prima che possa await ed esecuzione resa di nuovo al vostro flusso del programma in Main ().

Credo che i risultati che state vedendo sono dovute al fatto che ci vuole del tempo per creare e inviare la richiesta fuori dalla vostra macchina. In primo luogo quando questa sarà finito, l'attuazione di DownloadStringTaskAsync può attendere per la rete IO e il server remoto per completare, e può tornare esecuzione a voi.

D'altra parte, il metodo di RunOrdinaryTask solo inizializza un compito e gli dà un carico di lavoro, e gli dice di iniziare. Poi ritorna immediatamente. È per questo che non si vede un ritardo quando si utilizza RunOrdinaryTask.

Ecco alcuni link sul tema: di Eric Lippert blog (uno dei progettisti di linguaggi ), così come Jon di Skeet iniziale post del blog su di esso. Eric ha una serie di 5 post su stile continuazione-passing, che è davvero ciò che async e await è veramente. Se si vuole capire la nuova funzionalità in dettaglio, si potrebbe desiderare di leggere i messaggi di Eric su CPS e asincrone. In ogni modo, entrambi i collegamenti di cui sopra fa un buon lavoro a spiegare un fatto molto importante:

  • Asynchronous! = Parallelo

In altre parole, async e await non gira su nuove discussioni per voi. Hanno appena ti permette di riprendere l'esecuzione del flusso normale, quando si sta facendo un'operazione di blocco -. I tempi in cui la CPU sarebbe solo sedersi e non fare nulla in un programma sincrona, in attesa di qualche funzionamento esterno per completare

Modifica

Giusto per essere chiari su ciò che sta succedendo: set up DownloadStringTaskAsync una continuazione, quindi chiama WebClient.DownloadStringAsync, sullo stesso thread, e poi rendimenti esecuzione di nuovo al vostro codice. Pertanto, il tempo di blocco si sta vedendo prima del ciclo inizia il conteggio, è il tempo necessario per DownloadStringAsync completa. Il vostro programma con async e aspettano è molto vicino ad essere l'equivalente del seguente programma, che presenta lo stesso comportamento come programma: un blocco iniziale, inizia quindi contare, e da qualche parte nel mezzo, i asincroni finiture op e stampa il contenuto da l'URL richiesto:

    static void Main(string[] args)
    {
        WebClient cli = new WebClient();
        cli.DownloadStringCompleted += (sender, e) => Console.WriteLine(e.Result);
        cli.DownloadStringAsync(new Uri("http://www.weather.gov")); // Blocks until request has been prepared

        for (int i = 0; i < 15; i++)
        {
            Console.WriteLine(i);
            Thread.Sleep(100);
        }
    }

Nota: Sono in alcun modo un esperto su questo argomento, quindi potrei sbagliarmi su alcuni punti. Sentitevi liberi di correggere la mia comprensione del soggetto, se si pensa che questo sia sbagliato -. Ho appena guardato la presentazione PDC e ha giocato con l'ultima notte CTP

Altri suggerimenti

Sei sicuro che il problema non è legato alle impostazioni di configurazione del proxy viene rilevato da IE / Registry / Somewhere Slow?

Prova a impostare webClient.Proxy = null (o specificare le impostazioni in app.config) e il vostro "blocco" periodo dovrebbe essere minimo.

Stai premendo F5 o CTLR + F5 per eseguirla? Con F5 c'è un ritardo per VS solo per la ricerca di simboli per AsyncCtpLibrary.dll ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top