2014-01-14 11 views
5

Was ich tun muss, ist in der Lage, eine Aufgabe, die async ausgeführt wird, abzubrechen.Abbrechen Async Aufgabe von einer Schaltfläche

Ich habe gesucht und kann nicht scheinen, meinen Kopf darum zu wickeln. Ich kann einfach nicht erkennen, wie es in meinem aktuellen Setup umgesetzt werden würde.

Hier ist mein Code, der meine Aufgabe auslöst. Jede Hilfe, wo oder wie ein Stornierungs-Token implementiert wird, wäre sehr willkommen.

private async void startThread() 
    { 
     //do ui stuff before starting 
     ProgressLabel.Text = String.Format("0/{0} Runs Completed", index.Count()); 
     ProgressBar.Maximum = index.Count(); 

     await ExecuteProcesses(); 

     //sort list of output lines 
     outputList = outputList.OrderBy(o => o.RunNumber).ToList(); 

     foreach (Output o in outputList) 
     { 
      string outStr = o.RunNumber + "," + o.Index; 
      foreach (double oV in o.Values) 
      { 
       outStr += String.Format(",{0}", oV); 
      } 

      outputStrings.Add(outStr); 
     } 

     string[] csvOut = outputStrings.ToArray(); 

     File.WriteAllLines(settings.OutputFile, csvOut); 
     //do ui stuff after completing. 

     ProgressLabel.Text = index.Count() + " runs completed. Output written to file test.csv"; 
    } 

    private async Task ExecuteProcesses() 
    { 
     await Task.Factory.StartNew(() => 
     { 
      int myCount = 0; 
      int maxRuns = index.Count(); 
      List<string> myStrings = index; 
      Parallel.ForEach(myStrings, 
       new ParallelOptions() 
       { 
        MaxDegreeOfParallelism = settings.ConcurrentRuns 
       }, (s) => 
       { 
        //This line gives us our run count. 
        int myIndex = myStrings.IndexOf(s) + 1; 

        string newInputFile = Path.Combine(settings.ProjectPath + "files/", Path.GetFileNameWithoutExtension(settings.InputFile) + "." + s + ".inp"); 
        string newRptFile = Path.Combine(settings.ProjectPath + "files/", Path.GetFileNameWithoutExtension(settings.InputFile) + "." + s + ".rpt"); 

        try 
        { 
         //load in contents of input file 
         string[] allLines = File.ReadAllLines(Path.Combine(settings.ProjectPath, settings.InputFile)); 


         string[] indexSplit = s.Split('.'); 

         //change parameters here 
         int count = 0; 
         foreach (OptiFile oF in Files) 
         { 
          int i = Int32.Parse(indexSplit[count]); 
          foreach (OptiParam oP in oF.Parameters) 
          { 
           string line = allLines[oP.LineNum - 1]; 
           if (oP.DecimalPts == 0) 
           { 
            string sExpression = oP.Value; 
            sExpression = sExpression.Replace("%i", i.ToString()); 
            EqCompiler oCompiler = new EqCompiler(sExpression, true); 
            oCompiler.Compile(); 
            int iValue = (int)oCompiler.Calculate(); 

            allLines[oP.LineNum - 1] = line.Substring(0, oP.ColumnNum - 1) + iValue.ToString() + line.Substring(oP.ColumnNum + oP.Length); 
           } 
           else 
           { 
            string sExpression = oP.Value; 
            sExpression = sExpression.Replace("%i", i.ToString()); 
            EqCompiler oCompiler = new EqCompiler(sExpression, true); 
            oCompiler.Compile(); 
            double dValue = oCompiler.Calculate(); 
            dValue = Math.Round(dValue, oP.DecimalPts); 

            allLines[oP.LineNum - 1] = line.Substring(0, oP.ColumnNum - 1) + dValue.ToString() + line.Substring(oP.ColumnNum + oP.Length); 
           } 
          } 
          count++; 
         } 
         //write new input file here 
         File.WriteAllLines(newInputFile, allLines); 
        } 
        catch (IOException ex) 
        { 
         MessageBox.Show(ex.ToString()); 
        } 


        var process = new Process(); 
        process.StartInfo = new ProcessStartInfo("swmm5.exe", newInputFile + " " + newRptFile); 
        process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; 
        process.Start(); 
        process.WaitForExit(); 

        Output output = new Output(); 
        output.RunNumber = myIndex; 
        output.Index = s; 
        output.Values = new List<double>(); 

        foreach(OutputValue oV in OutputValues) { 
         output.Values.Add(oV.getValue(newRptFile)); 
        } 

        outputList.Add(output); 

        //get rid of files after run 
        File.Delete(newInputFile); 
        File.Delete(newRptFile); 

        myCount++; 
        ProgressBar.BeginInvoke(
         new Action(() => 
          { 
           ProgressBar.Value = myCount; 
          } 
        )); 
        ProgressLabel.BeginInvoke(
         new Action(() => 
          { 
           ProgressLabel.Text = String.Format("{0}/{1} Runs Completed", myCount, maxRuns); 
          } 
        )); 
       }); 
     }); 
    } 
+0

Ich habe keinen Code zur Hand, aber iirc benötigen Sie einen cancellationsource erstellen, erstellen Sie eine Löschung Token und übergeben diese In Ihrer StartTask (neben IProgress ) brechen Sie dann das Token über die Quelle in Ihrer Benutzeroberfläche ab und suchen in Ihrer asynchronen Methode nach IsCancelled. – Liath

+0

MSDN hat ein Beispiel http://msdn.microsoft.com/en-us/library/dd997396(v=vs.110).aspx – garf1eld

Antwort

10

Der beste Weg, Stornierung zu unterstützen, ist ein CancellationToken zur async Methode zu übergeben. Der Knopfdruck kann dann zum Abbrechen des Token

gebunden werden. Dies ist jedoch nicht genug, obwohl. Sowohl die startThread und StartProcess Methoden müssen aktualisiert werden, um gemeinsam die Aufgabe, sobald die CancellationToken Register abbrechen als annulliert

+0

Gute Antwort, aber mit jemand, der so viel wie das OP kämpft, könnte es nett sein, zu geben eine bessere Definition/ein Beispiel dessen, was "Kooperativ löschen" bedeutet. –

+0

Danke Jared, und auch Scott. Mir ist klar, dass meine Situation etwas seltener ist, als nur eine Aufgabe abzubrechen. Ich merke, dass ich den Prozess, den ich hervorgebracht habe, töten muss, und beende die Aufgabe. Ich bin einfach verloren, da ich online keinen Bezug zu einer ähnlichen Situation finden kann. –