2014-12-04 5 views
-2

logfile.txt에서 일부 항목을 대체하거나 제거해야하는 프로그램을 작성 중입니다. 코드가 정상적으로 작동하고 있습니다 (최소한 작은 LogFiles의 경우). 큰 파일 (예 : 27MB)을 사용하면 매우 느려지고 UI가 정지됩니다. 나는 아무것도 클릭 할 수 없다.UI Freezing and Computation 정말 느림

버튼에 나는이 방법을 실행하십시오

 private string delete_Lines(string[] lines, string searchString) 
    { 

     for (int i = 0; i < lines.Length; i++) 
     { 

      if (lines[i].Contains(searchString)) 
      { 
       rtbLog.Text += "Deleting(row " + (i + 1) + "):\n" + lines[i] + "\n"; 
       progressBar1.Value += 1; 
       if (cbDB == true) 
       { 
        while (is_next_line_block(lines, i) == true) 
        { 
         i++; 
         rtbLog.Text += lines[i] + "\n"; 
         progressBar1.Value += 1; 
        } 
       } 

      } 
      else 
      { 
       res += lines[i]+"\n"; 
       progressBar1.Value += 1; 
      } 

     } 
     tssLbl.Text = "Done!"; 
     rtbLog.Text += "...Deleting finished\n"; 
     return res; 
    } 

라인은 내가 청소하려고 로그 파일의 배열입니다. 모든 항목은 단일 행입니다. tssLbl은 알림 레이블이고 rtbLog는 richTextBox입니다. 여기서 i는 삭제할 행을 추적합니다.

is_next_line_block은 또 다른 방법으로, 다음 줄을 검사하는 것은 삭제하려는 블록의 일부입니다. 이 메소드의 매개 변수는 전체 행 배열과 행 위치입니다.

private bool is_next_line_block(string[] lines, int curIndex) 
    { 
     if (curIndex < lines.Length-1) 
     { 
      if (lines[curIndex + 1].StartsWith(" ")) 
      { 
       return true; 
      } 
      else 
      { 
       return false; 
      } 
     } 
     else 
     { 
      return false; 
     } 

    } 

아무 생각없는 사람, 그게 얼어 붙어서 프로그램 속도가 느려 집니까? 필자는 병렬화를 통해 코드를 빠르게 할 수는 있지만 병렬 처리가 필요없는 27 MB txt 파일을 확인하는 데 오랜 시간이 걸린다는 것을 알고 있습니다.

+0

'BackgroundWorker' _does_ 사용 스레드를, 그리고 특별히 진행 업데이트를 할 수 있도록 설계 UI에. 문제를 파악하는 데 어려움이있는 경우 구체적으로 질문하십시오. 성능에 관해서는 다른 스레딩 모델을 사용하여 성능을 변경하지는 않습니다. 27MB를 처리하는 데 시간이 오래 걸리면 해당 파일이 가장 느린 디스크에 저장되거나 처리 속도가 너무 느립니다. 어떤 경우이든이 예제를 좀 더 단순하게 좁히고 한 번에 한 이슈에만 집중해야합니다. http://stackoverflow.com/help/mcve 및 http://stackoverflow.com/help/how-to-ask –

+0

을 참조하십시오. 코드를 별도의 클래스로 옮기고 해당 클래스를 호출하면 적절한 매개 변수가 필요합니다. 지금 어떻게하고 있는지. 이제이 클래스를 인스턴스화하고'Task.Factory.시작()'을 클릭하고 앱이 여전히 느려지는지 여부를 알려주십시오. 시각적 큐 (예 : 진행률 막대 등)를 설정/해제해야하는 경우 '.ContinueWith'를 추가해야합니다. – code4life

+0

@PeterDuniho 내 질문과 코드 블록을 편집하므로 더 잘 읽을 수 있습니다. 제안을위한 ty. at code4life : 내가 정확히 당신을 이해하고 있음을 확인하십시오. 당신은 저의 전체 코드 (ui의 부분을 기대하십시오)를 새로운 클래스로 옮기고 거기에서 계산을하기를 원하십니까? 솔직히 말해서 Task.Factory.Start()에서 무엇을 의미하는지 알지 못합니다. 정확히 무엇을합니다. 계속 하시겠습니까? – Depa

답변

0

당신은 여기에 몇 가지 문제가 있습니다

당신은 버퍼에 전체 파일 (문자열의 배열)을 읽고
  1. , 나는()는 File.ReadAllLines를 호출하는 추측하고있다. 버퍼에 큰 파일을 읽으면 극한의 경우뿐만 아니라 메모리가 부족할 수도 있습니다.

  2. 서식있는 텍스트 입력 텍스트 속성에 + = operation을 사용하고 있습니다. 그렇게하면 텍스트 속성을 업데이트 할 때마다 UI가 전체 텍스트 상자를 렌더링해야하므로 시간이 오래 걸리는 작업입니다. 더 나은 옵션은 문자열 작성기를 사용하여이 텍스트를로드하고 주기적으로 서식있는 텍스트 상자를 업데이트하는 것입니다.

이 문제를 해결하려면 파일을 스트림으로 읽어야합니다. 진행은 행 위치 대신 읽은 바이트를 기반으로 모니터 할 수 있습니다. 아래 예제와 같이 타이머에서 읽기 작업 async 및 모니터 진행을 실행할 수 있습니다. (일반적으로)를 Task.Factory.Start() 사용에 대한 질문에 후속, 당신이 일을 끝낼 이런 식으로

private void RunFileOperation(string inputFile, string search) 
{ 
    Timer t = new Timer(); 
    int progress = 0; 
    StringBuilder sb = new StringBuilder(); 

    // Filesize serves as max value to check progress 
    progressBar1.Maximum = (int)(new FileInfo(inputFile).Length); 
    t.Tick += (s, e) => 
     { 
      rtbLog.Text = sb.ToString(); 
      progressBar1.Value = progress; 
      if (progress == progressBar1.Maximum) 
      { 
       t.Enabled = false; 
       tssLbl.Text = "done"; 
      } 
     }; 
    //update every 0.5 second  
    t.Interval = 500; 
    t.Enabled = true; 
    // Start async file read operation 
    System.Threading.Tasks.Task.Factory.StartNew(() => delete_Lines(inputFile, search, ref progress, ref sb));  
} 

private void delete_Lines(string fileName, string searchString, ref int progress, ref StringBuilder sb) 
{ 
    using (var file = File.OpenText(fileName)) 
    { 
     int i = 0; 
     while (!file.EndOfStream) 
     { 
      var line = file.ReadLine(); 
      progress = (int)file.BaseStream.Position; 
      if (line.Contains(searchString)) 
      { 
       sb.AppendFormat("Deleting(row {0}):\n{1}", (i + 1), line); 
       // Change this algorithm for nextline check 
       // Do this when it is next line, i.e. in this line. 
       // "If" check above can check if (line.startswith(" "))... 
       // instead of having to do it nextline next here. 
       /*if (cbDB == true) 
       { 
        while (is_next_line_block(lines, i) == true) 
        { 
         i++; 
         rtbLog.Text += lines[i] + "\n"; 
         progressBar1.Value += 1; 
        } 
       }*/ 
      } 
     } 
    }   
    sb.AppendLine("...Deleting finished\n"); 
} 
+0

은 매력처럼 작동합니다. 타이 rly. 약간의 조정이 필요하지만 주요 작업이 완료된 것 같습니다. 작업이 끝나면 작업 코드를 게시하십시오. 누군가이 문제의 작업 결과에 관심이있는 경우에 대비하십시오. 설명을 위해 – Depa

0

:이 도움이

// you might need to wrap this in a Dispatcher.BeginInvoke (see below) 
// if you are not calling from the main UI thread 
CallSomeMethodToSetVisualCuesIfYouHaveOne(); 

Task.Factory.StartNew(() => 
{ 
    // code in this block will run in a background thread... 
} 
.ContinueWith(task => 
{ 
    // if you called the task from the UI thread, you're probably 
    // ok if you decide not to wrap the optional method call below 
    // in a dispatcher begininvoke... 
    Application.Current.Dispatcher.BeginInvoke(new Action(()=> 
    { 
     CallSomeMethodToUnsetYourVisualCuesIfYouHaveAnyLOL(); 
    })); 
} 

희망! 도움, 특히 loopedcode을위한 모두에게

+0

타이. 이미 고쳐졌지만 마음에 들지 않게하십시오. – Depa

0

감사합니다, 즉 작동 버전입니다 (loopedcode의 코드를 가져다가 일부 편집 만든) :

 private void RunFileOperation(string inputFile, string search) 
    { 
     Timer t = new Timer(); 
     StringBuilder sb = new StringBuilder(); 
     { 
      rtbLog.Text = "Start Deleting...\n"; 
     } 


     // Filesize serves as max value to check progress 
     progressBar1.Maximum = (int)(new FileInfo(inputFile).Length); 
     t.Tick += (s, e) => 
     { 
      rtbLog.Text += sb.ToString(); 
      progressBar1.Value = progress; 
      if (progress == progressBar1.Maximum) 
      { 
       t.Enabled = false; 
       tssLbl.Text = "done"; 
      } 
     }; 
     //update every 0.5 second  
     t.Interval = 500; 
     t.Enabled = true; 
     // Start async file read operation 
     if (rbtnDelete.Checked) 
     { 
      if (cbDelete.Checked) 
      { 
       System.Threading.Tasks.Task.Factory.StartNew(() => delete_Lines(inputFile, search, ref progress, ref sb, ref res1)); 
      } 
    } 
    else 
    { 
     //..do something 
    } 

    private void delete_Lines(string fileName, string searchString, ref int progress, ref  StringBuilder sb, ref StringBuilder res1) 
    { 
    bool checkNextLine=false; 
     using (var file = File.OpenText(fileName)) 
     { 
      int i = 0; 
      while (!file.EndOfStream) 
      { 
       i++; 
       var line = file.ReadLine(); 
       progress = (int)file.BaseStream.Position; 
       if (line.Contains(searchString)) 
       { 
        sb.AppendFormat("Deleting(row {0}):\n{1}\n", (i), line); 
        checkNextLine = true; 
       } 
       else 
       { 
        if (cbDB && checkNextLine && line.StartsWith(" ")) 
        { 
         sb.AppendFormat("{0}\n", line); 
        } 
        else 
        { 
         checkNextLine = false; 
         res1.AppendLine(line); 

        } 
       } 

      } 
     } 
     sb.AppendLine("\n...Deleting finished!); 
    }