2016-10-06 3 views
-1

Ich habe ein Bedürfnis. Ich habe eine MVC5-Website. Ich verwende normale Contorller-Modellstruktur. Wo ich eine Controller-Funktion aus Javascript ausführe. Ich muss einige XML-Dateien verarbeiten, während sie hochgeladen werden. Was passiert, wenn der Controller die Funktion zum ersten Mal ausführt, kehrt er erst wieder zum Browser zurück, wenn alle XML-Dateien verarbeitet sind.MVC5 Wie verwende ich Async um eine progressive Aufgabe auszuführen?

Also hier ist was ich will. Ich möchte Controller-Funktion ausführen, um die Modellmethode auszuführen. In dieser Methode möchte ich alle XML-Dateien auswählen und dann asynchron verarbeiten. hier ist der Code:

var raw = new DirectoryInfo(xconfig.Directory.FullName + "//raw"); 
if (raw.Exists) 
{ 
    var xmls = raw.GetFiles("*.xml"); 
    foreach (var xml in xmls) 
    { 
     if(ProcessedXmlFiles != null) 
     { 
      if(!ProcessedXmlFiles.Contains(xml.Name)) 
      { 

       ExportData(xml); 
       ProcessedXmlFiles.Add(xml.Name); 
      } 
     } 
    } 
} 

Wenn der obige Code ausgeführt wird, ich einen anderen JavaScript-Methode aufrufen, um die Updates zu erhalten, wie viele Dateien verarbeitet wurden normale Ajax-Aufruf verwenden. Also rufe ich einfach eine andere Contrler-Methode auf, bei der ich die ProcessedXmlFiles.Count zurücksende, um zu wissen, wie viele von ihnen bisher verarbeitet wurden!

Antwort

1

Sie können einfach Ihre Aktion eine Task zurückgeben und Ihren Prozess in eine Task.Run platzieren.

public async Task<ActionResult> MyAction(object param) 
{ 
    var raw = new DirectoryInfo(xconfig.Directory.FullName + "//raw"); 
    if (raw.Exists) 
    { 
     await Task.Run(() => 
     { 
      var xmls = raw.GetFiles("*.xml"); 
      foreach (var xml in xmls) 
      { 
       if(ProcessedXmlFiles != null) 
       { 
        if(!ProcessedXmlFiles.Contains(xml.Name)) 
        { 
         ExportData(xml); 
         ProcessedXmlFiles.Add(xml.Name); 
        } 
       } 
      } 
     }); 
     // Do something 
    } 

    return View(); 
} 

EDIT: Da OP ein anderes Verhalten zu sein scheint erwarten als das, was die asynchrone Programmierung bieten kann, schlage ich vor, stattdessen einen Hintergrund Arbeiter verwenden, aber zur Kenntnis nehmen, dass die Arbeitnehmer in Web-Anwendungen Hintergrund mit nicht erwünscht ist. ASP.NET funktioniert in einer Anfrage-Antwort-Weise. Ich empfehle, den Benutzer warten zu lassen, bis der Prozess beendet ist, bevor die Ansicht gerendert wird.

public ActionResult MyAction(object param) 
{ 
    ExecuteBackgroundWorker(param); // your model containing the method you want to execute 
    return View(); // This will return the view while the background worker proceeds. 
} 

public void ExecuteBackgroundWorker(object param) 
{ 
    BackgroundWorker bgWorker = new BackgroundWorker(); 
    bgWorker.DoWork += bgWorker_DoWork; 
    bgWorker.RunWorkerCompleted += bgWorker_RunWorkerCompleted; 
    bgWorker.RunWorkerAsync(param); 
} 

void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    // Do Something when work ends 
} 

void bgWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    var OPsModel = (MyModel)e.Argument; // Cast object back to original model 
    OPsModel.ExecuteProcess(); // Execute the process 
} 
+0

gut dieser Code ist gut in einem Modell und es gibt nichts zurück! – KMX

+0

Nun, statt den Codeblock auszuführen, können Sie einfach das Innere von Task.Run durch 'myModel.ExecuteMethod()' ersetzen. Ob es etwas zurückgibt oder nicht, spielt keine Rolle. –

+0

Ich habe meine Controller-Methode wie folgt aktualisiert. Wenn der Code "processgallery" ausführt, kommt jeder Aufruf dieser API-Methode erst, wenn dies abgeschlossen ist. öffentlichen async Aufgabe Api() { if (Model.Api == "processgallery") { erwarten Task.Run (() => { Model.UpdateGallery(); }); Rückgabewert null; } sonst CallApi(); } – KMX

Verwandte Themen