2009-10-18 14 views
14

Mi plan es que un usuario escriba un título de película en mi programa y mi programa extraerá la información adecuada de forma asíncrona para que la UI no se congele.¿Cómo se usa el método WebClient.DownloadDataAsync() en este contexto?

Aquí está el código:

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; 
     } 

Mi problema real radica en el método WebClientX.DownloadDataAsync(). No puedo usar una URL de cadena para eso. ¿Cómo puedo usar esa función incorporada para descargar los bytes del sitio (para un uso posterior lo convertiré en una cadena, sé cómo hacerlo) y sin congelar mi GUI?

¿Quizás un ejemplo claro de DownloadDataAsync para que pueda aprender cómo usarlo?

Gracias SO, siempre eres un gran recurso.

+3

Re: IMDB página términos: "Los robots y captura de imágenes: Usted no puede utilizar minería de datos, robots, raspado de pantalla o herramientas similares de recolección y extracción de datos en este sitio, excepto con nuestro consentimiento expreso por escrito, como se indica a continuación ". Sugiero encarecidamente ** que hagas ** no ** esto; está claramente en contra de sus reglas. –

+1

Marc, ¿qué otro sitio tiene información como IMDB que PUEDO usar? Gracias por la ayuda. –

+0

Realmente no tengo idea. –

Respuesta

27

que necesita para manejar el 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"); 
} 

Los args contiene otros bits de información relativas a las condiciones de error, etc - verificar los mismos.

También tenga en cuenta que entrará en DownloadDataCompleted en un hilo diferente; Si está en una interfaz de usuario (winform, wpf, etc.), deberá acceder al hilo de la interfaz de usuario antes de actualizar la interfaz de usuario. Desde winforms, use this.Invoke. Para WPF, mira el Dispatcher.

+0

Solo para puntear-yo, hay un patrón estándar para manejar 'DownloadDataCompleted', como para' RunWorkerCompleted', ver 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

Si alguien utiliza arriba en aplicaciones web o sitios web, configure Async = "true" en la declaración de la directiva de la página en el archivo aspx.

20

Hay un método más nuevo DownloadDataTaskAsync que le permite esperar el resultado. Es más fácil de leer y más fácil de conectar con mucho. Que haría uso que ...

var client = new WebClient(); 

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

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

¿Pero hacer esto no es lo mismo que hacer la llamada de forma sincronizada? (Es DownloadDataTask y en este caso recibirá el resultado directamente), si desea hacer una llamada asincrónica, creo que esta no es una opción, porque funciona como sincronización. –

+0

Utiliza async/await con la clase Task. Es asíncrono tanto como la respuesta anterior. La única diferencia es que utilizas un método de continuación DownloadDataCompleted en el punto anterior y utilizas un await para alinear la continuación en mi versión.Si quería informes de progreso o algo similar, podría hacerlo de manera diferente, pero si solo quiere una continuación al finalizar de esta manera, funciona igual de bien con menos código. –

+1

Si desea hacer otras cosas mientras se ejecuta la tarea, simplemente no la espere y haga sus cosas, luego agregue una continuación. [Verifique esto para obtener información] (https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/chaining-tasks-by-using-continuation-tasks). –

0

// usando la clase 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); 
} 
Cuestiones relacionadas