2012-02-21 3 views
6

ho bisogno di fare richiesta asincrona a risorsa web e utilizzare ad esempio da questa pagina (link to full example):HttpWebRequest.BeginGetResponse

HttpWebRequest myHttpWebRequest= (HttpWebRequest)WebRequest.Create("http://www.contoso.com"); 
RequestState myRequestState = new RequestState(); 
myRequestState.request = myHttpWebRequest; 
// Start the asynchronous request. 
IAsyncResult result= 
     (IAsyncResult) myHttpWebRequest.BeginGetResponse(new AsyncCallback(RespCallback),myRequestState); 

Ma quando sto testando l'applicazione del blocco di esecuzione (il 2-3 sec) su l'ultima riga di questo codice (posso guardarlo usando il debugger).

Perché? È un mio errore o è un comportamento standard della funzione?

risposta

6

Si può provare, io sono sicuro questo è meglio

private void StartWebRequest(string url) 
{ 
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 
    request.BeginGetResponse(new AsyncCallback(FinishWebRequest), request); 
} 

private void FinishWebRequest(IAsyncResult result) 
{ 
    HttpWebResponse response = (result.AsyncState as HttpWebRequest).EndGetResponse(result) as HttpWebResponse; 
} 

A causa del filo chross di textbox'value, ma questa è un'applicazione WPF io sostituire i tag questo, btw è possibile utilizzare webclient come

private void tbWord_TextChanged(object sender, TextChangedEventArgs e) 
    { 
     WebClient wc = new WebClient(); 
     wc.DownloadStringCompleted += HttpsCompleted; 
     wc.DownloadStringAsync(new Uri("http://en.wikipedia.org/w/api.php?action=opensearch&search=" + tbWord.Text)); 
    } 
    private void HttpsCompleted(object sender, DownloadStringCompletedEventArgs e) 
    { 
     if (e.Error == null) 
     { 

      //do what ever 
      //with using e.Result 
     } 
    } 
+0

Che cos'è il parametro IAsyncResult nel secondo metodo? Risultato della richiesta di chiamata.BeginGetResponse()? – demas

+0

Come vedo io non cambia nulla. Ecco il codice completo http://pastebin.com/trvq1qza. Windows GUI congelare sulla linea 18. – demas

+0

@demas ho aggiornato la risposta. –

1

È possibile utilizzare BackgroundWorker aggiungere fare il tutto in DoWork

2

la risposta si verifica in un thread separato. Le Winform non sono multi-thread safe, quindi dovrai inviare la chiamata sullo stesso thread del modulo.

È possibile farlo utilizzando il ciclo di messaggi interno della finestra. Fortunatamente, .NET offre un modo per farlo. È possibile utilizzare i metodi Invoke o BeginInvoke del controllo per eseguire questa operazione. Il primo blocca il thread corrente fino a quando il thread UI completa il metodo invocato. Più tardi lo fa in modo asincrono. A meno che non ci sia la pulizia da fare, è possibile utilizzare quest'ultimo per "accendere e dimenticare"

Per far sì che funzioni in entrambi i casi, è necessario creare un metodo che viene richiamato da BeginInvoke e che è necessario un delegato per indicare quel metodo.

Vedere Control.Invoke e Control.BeginInvoke nel MSDN per ulteriori dettagli.

C'è un campione a questo link: https://msdn.microsoft.com/en-us/library/zyzhdc6b(v=vs.110).aspx

Aggiornamento: Come sto navigando il mio profilo perché ho dimenticato ho avuto un account qui - ho notato questo e devo aggiungere: Tutto passato, 3,5 o quando in modo significativo cambiato il modello di threading asincrono qui è fuori dalla mia timoneria. Sono fuori professionalmente, e mentre amo ancora il mestiere, non seguo ogni progresso. Quello che posso dirti è che questo dovrebbe funzionare in tutte le versioni di .NET ma potrebbe non essere l'assoluto apice delle prestazioni 4.0 e successive o sull'emulazione Mono/Winforms se è ancora in circolazione. Sul lato positivo, qualsiasi hit di solito non sarà negativo al di fuori delle app del server e persino all'interno se il threadpool sta facendo il suo lavoro. Quindi non concentrare gli sforzi di ottimizzazione qui nella maggior parte dei casi, ed è più probabile che si lavori su piattaforme "spogliate" che si vedono eseguire cose come i pacchetti mobili C# anche se dovrei cercare di essere sicuro e la maggior parte non esegue winforms ma alcuni giri di messaggi e questo funziona anche lì. Fondamentalmente alla linea di fondo, non è la "migliore risposta" per le piattaforme più recenti in ogni caso. Ma potrebbe essere più portatile nel caso giusto. Se ciò aiuta una persona a evitare di fare un errore di progettazione, allora è valsa la pena il tempo che ho impiegato per scrivere questo. =)

1

È il comportamento standard.

Dal documentation on HttpWebRequest.BeginGetResponse Method:

Procedimento BeginGetResponse richiede alcune impostazioni sincroni per completare (risoluzione DNS, rilevamento proxy e connessione socket TCP, per esempio) prima che questo metodo diventa asincrono. [...] potrebbe richiedere molto tempo (fino a diversi minuti a seconda delle impostazioni di rete) per completare le attività di configurazione sincrone iniziali prima che venga generata un'eccezione per un errore o che il metodo abbia esito positivo.

Per evitare in attesa della messa a punto, è possibile utilizzare HttpWebRequest.BeginGetRequestStream Method ma essere consapevoli che:

L'applicazione non può mescolare i metodi sincroni e asincroni per una particolare richiesta. Se si chiama il metodo BeginGetRequestStream, è necessario utilizzare il metodo BeginGetResponse per recuperare la risposta.