Domanda

Sto sviluppando un'applicazione C # WinForms, parte della domanda sarà il caricamento di file su un server web usando AsyncUpload (ad usarlo, a causa della necessità di utilizzare un callback porgress), Nel programma C #

ho ottenuto un semplice ciclo for che chiama la funzione Caricamento

 for(int i=0;i < 10 ; i++)
{
  Uploadfun();
}

E il divertimento non qualche magia:

Uploadfun()
  { 
  // Logic comes here

   // webClient.UploadFileAsync runs a 2nd thread to perform upload .. 
   webClient.UploadFileAsync(uri, "PUT", fileNameOnHD);  

 }

E un callback che viene chiamata quando il caricamento asincrono è fatto

Upload_Completed_callback()
{
  //Callback event
}

Modifica

La sequenza logica:

  1. Divertimento viene chiamato (da anello)
  2. logica divertimento è eseguito e fatto ..
  3. Ritorna alla ciclo for
  4. callback verrà chiamata casualmente, quando UploadFileAsync (che esegue una logica in un altro thread) finirà

Il problema è al 3 ° punto, quando l'esecuzione si sposta di nuovo al ciclo for, ho bisogno di bloccare il ciclo di continuare fino a quando il callback vengono chiamati.

È stato utile?

Soluzione

Quindi, se ho capito bene, si desidera chiamare UploadFileAsync quindi bloccare fino a quando la chiamata asincrona ha colpito il callback. Se è così, mi piacerebbe utilizzare AutoResetEvent cioè

private readonly AutoResetEvent _signal = new AutoResetEvent(false); 

fun()
  { 
  // Logic comes here

   // runs a 2nd thread to perform upload .. calling "callback()" when done
   webClient.UploadFileAsync(uri, "PUT", fileNameOnHD);  

   _signal.WaitOne();   // wait for the async call to complete and hit the callback     
 }



callback()
 {
   //Callback event
   _signal.Set(); // signal that the async upload completed
 }

Uso AutoResetEvent significa che lo stato viene resettato automaticamente dopo Set è stata chiamata e un filo attesa riceve il segnale tramite WaitOne

Altri suggerimenti

In C # i metodi blocco di default, quindi non dovrebbe essere necessario fare nulla. Sto assumendo che per qualche motivo si sta chiamando un metodo non-blocking che inizia uno sfondo compito / thread / qualunque cosa e ti dà un callback quando è fatto. Si desidera chiamare questo metodo asynchonous in modo sincrono.

È possibile chiamare fun dall'interno della richiamata. Qualcosa in questo senso (pseudo-codice):

int n;

callFunTenTimes()
{
    n = 0;
    fun(n);
}

callback()
{
    ++n;
    if (n < 10)
       fun(n);
    else
       print("done");
}

Questo è simile a passando stile .

Un vantaggio di questo metodo è che si può anche fare il vostro metodo asincrono senza l'aggiunta di fili aggiuntivi, serrature, o la logica in più - voi appena fornisce una funzione di callback che il vostro cliente può sottoscrivere. Funziona bene in un ambiente event-driven.

Zebrabox non ce l'ha proprio con un WaitHandle. Mentre la soluzione di Giulietta funziona, il filo eseguendo lo spin-wait consumerà una quantità significativa di processore in proporzione alla WaitHandle, che sarebbe essenzialmente seduto inattivo.

Il problema è qui:

for(int i=0;i < 10 ; i++)
{
  fun(); <-- if we block until this function finishes here, we stop the UI thread
}

Quello che stai facendo è sequenziale. E se non si può permettere di bloccare il thread UI, spostare l'anello fuori dal thread dell'interfaccia utente:

volatile downloadComplete;

void DownloadUpdates()
{
    ThreadPool.QueueUserWorkItem(state =>
        for(int i = 0; i < 10; i++)
        {
            downloadComplete = false;
            webClient.UploadFileAsync(uri, "PUT", fileNameOnHD);
            while(!downloadComplete) { Thread.Sleep(1); }
        });
}

Upload_Completed_callback()
{
    downloadComplete = true;
}

Ora è possibile bloccare l'esecuzione del ciclo, senza arrestare il tuo thread dell'interfaccia utente, e si ottiene anche il vantaggio di indicatori di avanzamento dalla classe WebClient.

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