2012-01-24 44 views
2

我有一個小應用程序,讀取管道delimted文件並寫出線的RTB,強調如果有dissallowed在一定的「列」字從BackgroundWorker的一個RichTextBox。這是完美的工作......但是,用戶需要一個進度條,並且看到正在寫入的行「實時」,並且能夠在中途取消。如何更新使用的BeginInvoke

我有一直在使用寫入到一個RichTextBox,同時阻擋UI以下擴展方法,但是這種失敗使用具有BeginInvoke的一個BackgroundWorker。

的失敗是查找文本的當前長度時。

public static void AppendLine(this RichTextBox richTextBox, string text, List<Char> foundChars, List<int> columns) 
     { 
      var split = text.Trim().Split(new char[] { '|' }); 

      for (int i = 0; i < split.Count(); i++) 
      { 
       **var start = richTextBox.TextLength;** 
       richTextBox.AppendText(split[i]); 
       var end = richTextBox.TextLength; 

       if (columns.Contains(i + 1)) 
       { 
        foreach (var foundChar in foundChars) 
        { 
         var current = start; 

         while (current > 0) 
         { 
          var position = richTextBox.Find(new char[] { foundChar }, current, end); 
          current = position + 1; 
          if (current > 0) 
          { 
           richTextBox.Select(position, 1); 
           richTextBox.SelectionColor = Color.Red; 
          } 
         } 
        } 
       } 
       richTextBox.SelectionLength = 0; 
       richTextBox.SelectionColor = Color.Black; 
      } 
      richTextBox.AppendLine(); 
     } 

private void UpdateResultsLine(string line, List<char> foundChars) 
     { 
      if (txtResults.InvokeRequired) 
      { 
       txtResults.BeginInvoke(new UpdateResultsLineDelegate(UpdateResultsLine), line, foundChars); 
      } 
      txtResults.AppendLine(line, foundChars, _fileType.ProcessColumns); 
     } 

但是,如果我叫任何/所有以同樣的方式這些擴展的,他們的工作?

public static void AppendLine(this RichTextBox richTextBox) 
{ 
    richTextBox.AppendText(Environment.NewLine); 
} 

public static void AppendLine(this RichTextBox richTextBox, string text) 
{ 
    richTextBox.AppendText(text + Environment.NewLine); 
} 

public static void AppendLine(this RichTextBox richTextBox, string text, params object[] args) 
{ 
    richTextBox.AppendLine(string.Format(text, args)); 
} 

我在想什麼?還是有另一種方法可以將彩色文字寫入RTB?

+1

使用'BackgroundWorker'組件的一點是,你在更新了'ProgressChanged'和/或'RunWorkerCompleted'事件處理方法的UI。你根本不需要使用'BeginInvoke'。請參閱MSDN上的示例[此處](http://msdn.microsoft.com/zh-cn/library/system.componentmodel.backgroundworker.aspx)。 –

+0

對不起,但這並不符合我的全部要求。我需要更新一個以上的RTB,另外可能還有一個標籤和進度條。是的,我可以創建一個新的對象來傳遞,包含一個Enum來說明需要更新哪些內容並切換到每個ProgressChanged調用中,但這似乎過分了。 – BlueChippy

+0

我不明白你爲什麼不能更新'ProgressChanged'事件處理器方法中的多個控件。你不需要創建任何對象或傳遞它們。處理這些事件的關鍵是它們在UI線程中引發。 –

回答

5

你在你的UpdateResultsLine方法需要一個else聲明。當需要Invoke,您正在執行使用(調用)委託的UpdateResultsLine方法,但你再次調用,而無需使用Invoke

另外,爲什麼要使用BeginInvoke(異步),並使用Invoke(同步)?你確定你沒有同步問題嗎?使用Invoke並添加else語句可以解決你的問題:

private void UpdateResultsLine(string line, List<char> foundChars) 
{ 
    if (txtResults.InvokeRequired) 
    { 
     txtResults.Invoke(
      new UpdateResultsLineDelegate(UpdateResultsLine), 
      line, 
      foundChars); 
    } 
    else 
    { 
     txtResults.AppendLine(
      line, 
      foundChars, 
      _fileType.ProcessColumns); 
    } 
} 
+0

我通過添加「else」子句得到了一半,但BeginInvoke - > Invoke爲我排序。 Thx – BlueChippy

6

在這裏,你可以嘗試一下,創建擴展類如下

public static class ControlExtensions 
{ 
    public static void Invoke(this Control control, Action action) 
    { 
     if (control.InvokeRequired) control.Invoke(new MethodInvoker(action), null); 
     else action.Invoke(); 
    } 
} 

而且當過和任何你要更新什麼用戶界面,你只需要做

richTextBox.Invoke(() => { richTextBox.AppendText(text + Environment.NewLine); }); 

希望這適用於你。

+0

丹尼爾首先回答,我實現了他的解決方案,以便他得到要點...但是我可能會轉而選擇這個,因爲我喜歡清晰度。 – BlueChippy

+0

不是問題。我很高興你得到了這些信息。 –

+0

也許更好BeginInvoke http://kristofverbiest.blogspot.com/2007/02/avoid-invoke-prefer-begininvoke.html – Kiquenet