2014-01-14 2 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

취소 할 수있는 코드가 없지만 취소 소스를 만들고 취소 토큰을 생성하고 전달해야합니다. StartTask (IProgress 옆)에 입력 한 다음 UI의 소스를 통해 토큰을 취소하고 비동기 메서드에서 IsCancelled를 확인합니다. – Liath

+0

MSDN에 예제가 있습니다. http://msdn.microsoft.com/en-us/library/dd997396(v=vs.110).aspx – garf1eld

답변

10

소거를 지원하기위한 가장 좋은 방법은 async 방법에 CancellationToken를 전달하는 것이다. 그러면 토글을 취소하기 위해 버튼을 누를 수 있습니다.

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에게 감사드립니다. 나는 나의 상황이 단지 일을 취소하는 것보다 조금 덜 일반적이라는 것을 깨닫는다. 나는 내가 산란 한 과정을 죽이고 그 일을 끝내야한다고 생각합니다. 비슷한 상황에 대한 온라인 참조를 찾을 수 없기 때문에 단순히 잃어버린 것입니다. –