2009-10-18 10 views
14

Il mio piano è di fare in modo che un utente scriva un titolo di un film nel mio programma e il mio programma estrarrà le informazioni appropriate in modo asincrono in modo che l'interfaccia utente non si blocchi.Come utilizzare il metodo WebClient.DownloadDataAsync() in questo contesto?

Ecco il codice:

public class IMDB 
    { 
     WebClient WebClientX = new WebClient(); 
     byte[] Buffer = null; 


     public string[] SearchForMovie(string SearchParameter) 
     { 
      //Format the search parameter so it forms a valid IMDB *SEARCH* url. 
      //From within the search website we're going to pull the actual movie 
      //link. 
      string sitesearchURL = FindURL(SearchParameter); 

      //Have a method download asynchronously the ENTIRE source code of the 
      //IMDB *search* website. 
      Buffer = WebClientX.DownloadDataAsync(sitesearchURL); 


      //Pass the IMDB source code to method findInformation(). 

      //string [] lol = findInformation(); 

      //???? 

      //Profit. 

      string[] lol = null; 
      return lol; 
     } 

Il mio vero problema risiede nel metodo WebClientX.DownloadDataAsync(). Non posso usare un URL di stringa per questo. Come posso usare quella funzione incorporata per scaricare i byte del sito (per un uso futuro lo convertirò in stringa, so come farlo) e senza congelare la mia GUI?

Forse un chiaro esempio di DownloadDataAsync così posso imparare a usarlo?

Grazie COSÌ, sei sempre una grande risorsa.

+3

Re IMDB: la pagina termini: "Robot e screen scraping: non è possibile effettuare data mining, robot, screen scraping o strumenti simili per la raccolta e l'estrazione di dati su questo sito, tranne che con il nostro esplicito consenso scritto come indicato di seguito. ". Io ** consiglio vivamente ** di fare ** non ** questo; è chiaramente contro le loro regole. –

+1

Marc, quale altro sito ha informazioni come IMDB che posso usare? Grazie per l'aiuto. –

+0

Non ne ho idea. –

risposta

27

è necessario gestire l'evento DownloadDataCompleted:

static void Main() 
{ 
    string url = "http://google.com"; 
    WebClient client = new WebClient(); 
    client.DownloadDataCompleted += DownloadDataCompleted; 
    client.DownloadDataAsync(new Uri(url)); 
    Console.ReadLine(); 
} 

static void DownloadDataCompleted(object sender, 
    DownloadDataCompletedEventArgs e) 
{ 
    byte[] raw = e.Result; 
    Console.WriteLine(raw.Length + " bytes received"); 
} 

Gli args contiene altri bit di informazioni in materia di condizioni di errore, ecc - controllare quelli troppo.

Nota inoltre che entrerai in DownloadDataCompleted su un thread diverso; se si è in una UI (winform, wpf, ecc.) è necessario accedere al thread dell'interfaccia utente prima di aggiornare l'interfaccia utente. Da winforms, utilizzare this.Invoke. Per WPF, guarda lo Dispatcher.

+0

Solo per dot-the-i, esiste un modello standard per la gestione di 'DownloadDataCompleted', come per' RunWorkerCompleted', vedere http://msdn.microsoft.com/en-us/library/cc221403%28VS.95 % 29.aspx –

2
static void Main(string[] args) 
{ 
    byte[] data = null; 
    WebClient client = new WebClient(); 
    client.DownloadDataCompleted += 
     delegate(object sender, DownloadDataCompletedEventArgs e) 
     { 
      data = e.Result; 
     }; 
    Console.WriteLine("starting..."); 
    client.DownloadDataAsync(new Uri("http://stackoverflow.com/questions/")); 
    while (client.IsBusy) 
    { 
     Console.WriteLine("\twaiting..."); 
     Thread.Sleep(100); 
    } 
    Console.WriteLine("done. {0} bytes received;", data.Length); 
} 
2

Se qualcuno che utilizza in precedenza nelle applicazioni Web o nei siti Web, impostare Async = "true" nella dichiarazione della direttiva della pagina nel file aspx.

20

C'è un nuovo metodo DownloadDataTaskAsync che consente di attendere il risultato. È più semplice da leggere e più facile da cablare di gran lunga. Userei che ...

var client = new WebClient(); 

var data = await client.DownloadDataTaskAsync(new Uri(imageUrl)); 

await outstream.WriteAsync(data, 0, data.Length); 
+0

Ma fare questo non è lo stesso per effettuare la chiamata in modo sincrono? (È DownloadDataTask e in questo caso riceverai il risultato direttamente), se vuoi fare una chiamata asincrona penso che questa non sia un'opzione, perché funziona come la sincronizzazione. –

+0

Usa async/attende con la classe Task. È asincrono tanto quanto la risposta di cui sopra è. L'unica differenza è che si utilizza un metodo di continuazione DownloadDataCompleted in quanto sopra e si utilizza l'attesa per incorporare la continuazione nella mia versione.Se si desidera la segnalazione di avanzamento o simili, potrei farlo in modo diverso, ma se si desidera una continuazione al completamento, in questo modo funziona altrettanto bene con meno codice. –

+1

Se vuoi fare altre cose mentre il Task è in esecuzione, non aspettarlo e fare le tue cose, quindi aggiungere una continuazione ad esso. [Controlla questo per informazioni] (https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/chaining-tasks-by-using-continuation-tasks). –

0

// utilizzando la classe ManualResetEvent

static ManualResetEvent evnts = new ManualResetEvent(false); 
static void Main(string[] args) 
{ 
    byte[] data = null; 
    WebClient client = new WebClient(); 
    client.DownloadDataCompleted += 
     delegate(object sender, DownloadDataCompletedEventArgs e) 
     { 
      data = e.Result; 
      evnts.Set(); 
     }; 
    Console.WriteLine("starting..."); 
    evnts.Reset(); 
    client.DownloadDataAsync(new Uri("http://stackoverflow.com/questions/")); 
    evnts.WaitOne(); // wait to download complete 

    Console.WriteLine("done. {0} bytes received;", data.Length); 
} 
Problemi correlati