Frage

ich eine C # WinForms-Anwendung entwickle, Teil der Anwendung wird Dateien auf einen Webserver hochladen AsyncUpload mit (unter Verwendung es, aufgrund der Notwendigkeit, einen porgress Rückruf zu verwenden), in dem C # Programm

Ich habe eine einfache for-Schleife, die das Hochladen Funktion aufruft

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

Und der Spaß hat einige Magie:

Uploadfun()
  { 
  // Logic comes here

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

 }

Und ein Rückruf, der aufgerufen wird, wenn das Async-Upload erfolgt

Upload_Completed_callback()
{
  //Callback event
}

Bearbeiten

Die logische Folge:

  1. Spaß wird aufgerufen (von Loop)
  2. Spaß Logik ausgeführt wird und getan ..
  3. Geht zurück auf for-Schleife
  4. Rückruf schließlich aufgerufen wird, wenn UploadFileAsync (die in einem anderen Thread eine gewisse Logik läuft) endet

Das Problem auf dem dritten Punkt ist, wenn die Ausführung für Schleife das bewegt sich zurück, ich brauche die Schleife zu blockieren, fortgesetzt wird, bis der Rückruf aufgerufen.

War es hilfreich?

Lösung

Also, wenn ich das richtig verstehen, wollen Sie UploadFileAsync rufen dann blockieren, bis der Asynchron Anruf Ihren Rückruf getroffen. Wenn ja, würde ich AutoResetEvent d.h verwenden

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
 }

AutoResetEvent Verwendung bedeutet, dass der Zustand automatisch zurückgesetzt wird, nachdem Set genannt wurde und ein wartenden Thread empfängt das Signal über WaitOne

Andere Tipps

In C # Methoden blockieren standardmäßig, so dass Sie sollten nichts tun müssen. Ich gehe davon aus, dass Sie aus irgendeinem Grund eine nicht-blockierende Methode aufrufen, die eine Hintergrundaufgabe / Thread startet / was auch immer und gibt Ihnen einen Rückruf, wenn es fertig ist. Sie mögen diese asynchrone Methode in einer synchronen Weise nennen.

können Sie rufen fun aus dem Inneren der Rückruf. Etwas in dieser Richtung (Pseudo-Code):

int n;

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

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

Dies ist ähnlich href="http://en.wikipedia.org/wiki/Continuation-passing_style" rel="nofollow noreferrer"> Fortsetzung vorbei Stil

Ein Vorteil dieser Methode ist, dass man auch ohne Zugabe von zusätzlichen Threads, Sperren Sie Ihre Methode asynchron machen können, oder zusätzliche Logik - man muss nur eine Callback-Funktion liefern, die Ihre Kunden abonnieren. Es funktioniert gut in einer ereignisgesteuerten Umgebung.

Zebrabox hat es ein Waithandle rechten Seite. Während Julias Lösung funktioniert, verbraucht der Thread die Spin-Warte Durchführung eine erhebliche Menge an Prozessor im Verhältnis zu der Waithandle, die im wesentlichen untätig sitzen würden.

Das Problem ist hier:

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

Was Sie tun, ist sequentiell. Und wenn Sie sich nicht leisten, den UI-Thread zu blockieren, um die Schleife aus dem UI-Thread verschieben:

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

Nun können Sie die Ausführung der Schleife blockieren, ohne Ihren UI-Thread zu stoppen, und Sie haben auch den Vorteil der Fortschrittsindikatoren aus der WebClient-Klasse erhalten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top