2014-01-14 100 views
5

我需要做的是能夠取消正在運行異步的任務。取消按鈕的異步任務

我一直在尋找,似乎無法包圍我的頭。我似乎無法辨別它將如何實施到我目前的設置中。

這是我的代碼,我的任務關閉。任何幫助在何處或如何實施取消令牌將不勝感激。

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

我沒有任何代碼的手,但IIRC你需要創建一個cancellationsource,創建取消標記,並通過這到您的StartTask(IProgress 旁邊),然後您通過UI中的源代碼取消令牌並在異步方法中檢查IsCancelled。 – Liath

+0

MSDN有一個例子http://msdn.microsoft.com/en-us/library/dd997396(v=vs.110).aspx – garf1eld

回答

10

支持消除最好的方法是將一個CancellationToken傳遞給async方法。然後按鈕按可取消令牌

class TheClass 
{ 
    CancellationTokenSource m_source; 

    void StartThread() { 
    m_source = new CancellationTokenSource; 
    StartThread(m_source.Token); 
    } 

    private async void StartThread(CancellationToken token) { 
    ... 
    } 

    private void OnCancelClicked(object sender, EventArgs e) { 
    m_source.Cancel(); 
    } 
} 

雖然這還不夠。無論是startThreadStartProcess方法都需要進行更新,以配合取消任務一旦CancellationToken寄存器,取消

+0

很好的答案,但有人與OP一樣掙扎,它可能是很好給「合作取消」意味着什麼更好的定義/例子。 –

+0

謝謝Jared,還有Scott。我意識到我的情況不像取消任務那麼普遍。我意識到我需要殺死我產生的過程,並結束任務。我簡直失去了,因爲我找不到任何類似情況的參考。 –