2016-03-04 20 views
0

更新凍結這是迄今爲止我的項目:C#,WPF - > GUI不應該,而在BackgroundWorker的

private void test() 
    { 
     var rows = GetDataGridRows(dgVarConfig); 

     Dictionary<TextBlock, String> dic = new Dictionary<TextBlock, string>(); 
     foreach (DataGridRow r in rows) 
     { 
      TextBlock tb = cMatchEx.GetCellContent(r) as TextBlock; 
      dic.Add(tb, tb.Text); 
     } 

     if (!syntaxWorker.IsBusy) 
      syntaxWorker.RunWorkerAsync(dic); 
    } 



    private void syntaxWorker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     if (e.Argument == null) 
      Thread.Sleep(100); 
     else 
     { 
      Dictionary<TextBlock, String> dic = (Dictionary<TextBlock, String>)e.Argument; 

      foreach (KeyValuePair<TextBlock, String> kvp in dic) 
      { 

       kvp.Key.Dispatcher.BeginInvoke(new Action(() => 
       { 
        kvp.Key.Inlines.Clear(); 
        Syntax.Highlight(kvp.Value).ForEach(x => kvp.Key.Inlines.Add(x)); 
       })); 
      } 

     } 
    } 

Syntax.Highlight:

public static class Syntax 
{ 
    static Regex subFormula = new Regex(@"\w+\(\)"); 
    static Regex sapFormula = new Regex(@"\w+\(([^)]+)\)"); 
    static Regex strings = new Regex(@"\'[^']+\'"); 
    static Regex numerals = new Regex(@"\b[0-9\.]+\b"); 
    static Regex characteristic = new Regex(@"(?:)?\w+(?:)?"); 
    static Regex andOr = new Regex(@"(and)|(AND)|(or)|(OR)"); 
    static Regex not = new Regex(@"(not)|(NOT)"); 

    private static Brush[] colorArray; 

    public static List<Run> Highlight(String input) 
    { 


     colorArray = new Brush[input.Length]; 

     for (int i = 0; i < input.Length; i++) 
      colorArray[i] = Brushes.Black; 

     //Reihenfolge beibehalten!! 
     assignColor(Brushes.Blue, characteristic.Matches(input)); 
     assignColor(Brushes.Black, andOr.Matches(input)); 
     assignColor(Brushes.Black, numerals.Matches(input)); 
     assignColor(Brushes.Orange, strings.Matches(input)); 
     assignColor(Brushes.DeepPink, subFormula.Matches(input)); 
     assignColor(Brushes.Green, sapFormula.Matches(input)); 
     assignColor(Brushes.Green, not.Matches(input)); 


     int index = 0; 

     List<Run> runList = new List<Run>(); 

     foreach (Char character in input) 
     { 

      runList.Add(new Run(character.ToString()) { Foreground = colorArray[index] }); 
      index++; 
     } 


     colorArray = null; 
     return runList; 
    } 

    public static void Check(TextBlock textBlock) 
    { 

    } 


    private static void assignColor(Brush brush, MatchCollection matchCollection) 
    { 
     foreach (Match match in matchCollection) 
     { 
      int start = match.Index; 
      int end = start + match.Length; 

      for (int i = start; i < end; i++) 
      { 
       colorArray[i] = brush; 
      } 
     } 
    } 
} 

有了這個代碼,以獲取有關GUI凍結2秒。有什麼辦法可以逐步建立GUI並避免任何凍結? 它沒有問題,看它如何建立,只是凍結是一個問題。

希望有人知道如何解決這個問題。

+4

凍結的原因是背景工作程序基本上沒有實現它的方式;只有循環邏輯在後臺執行,因爲工作的主要內容是在「Dispatcher.BeginInvoke」中。嘗試找到一種方法來更快地創建「突出顯示(字符串輸入)」,或者將其邏輯移動到自己的後臺工作者或線程。 (您可以在完成一次事件後更新事件以更新控件的視覺效果,或在末尾調用UI線程) –

+0

以及我如何實現該目標?我不能建立一個運行,並用它更新文本塊 –

+0

你絕對可以在後臺線程中編譯運行。 –

回答

1

你可以像這樣的調用外部移動工作的一個很好的部分:

一個小小的警告:我不完全相信你如何retreive文本框的文本。您可能需要爲此單獨調用(請參閱代碼中的註釋)

public class RunInfo 
{ 
    public string Content { get; set;} 
    public Color foreground { get; set; } 
    public RunInfo(string content) 
    { 
     Content = content; 
    } 

    public Run AsRun() 
    { 
     return new Run(Content){ Foreground = foreground }; 
    } 

} 



public static class Syntax 
{ 
    static Regex subFormula = new Regex(@"\w+\(\)"); 
    static Regex sapFormula = new Regex(@"\w+\(([^)]+)\)"); 
    static Regex strings = new Regex(@"\'[^']+\'"); 
    static Regex numerals = new Regex(@"\b[0-9\.]+\b"); 
    static Regex characteristic = new Regex(@"(?:)?\w+(?:)?"); 
    static Regex andOr = new Regex(@"(and)|(AND)|(or)|(OR)"); 
    static Regex not = new Regex(@"(not)|(NOT)"); 

    private static Brush[] colorArray; 

    public static List<RunInfo> Highlight(String input) 
    { 


     colorArray = new Brush[input.Length]; 

     for (int i = 0; i < input.Length; i++) 
      colorArray[i] = Brushes.Black; 

     //Reihenfolge beibehalten!! 
     assignColor(Brushes.Blue, characteristic.Matches(input)); 
     assignColor(Brushes.Black, andOr.Matches(input)); 
     assignColor(Brushes.Black, numerals.Matches(input)); 
     assignColor(Brushes.Orange, strings.Matches(input)); 
     assignColor(Brushes.DeepPink, subFormula.Matches(input)); 
     assignColor(Brushes.Green, sapFormula.Matches(input)); 
     assignColor(Brushes.Green, not.Matches(input)); 


     int index = 0; 

     List<Run> runList = new List<Run>(); 

     foreach (Char character in input) 
     { 

      runList.Add(new RunInfo(character.ToString()) { Foreground = colorArray[index] }); 
      index++; 
     } 


     colorArray = null; 
     return runList; 
    } 

    public static void Check(TextBlock textBlock) 
    { 

    } 


    private static void assignColor(Brush brush, MatchCollection matchCollection) 
    { 
     foreach (Match match in matchCollection) 
     { 
      int start = match.Index; 
      int end = start + match.Length; 

      for (int i = start; i < end; i++) 
      { 
       colorArray[i] = brush; 
      } 
     } 
    } 
} 




private void syntaxWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    if (e.Argument == null) 
     Thread.Sleep(100); 
    else 
    { 
     Dictionary<TextBlock, String> dic = (Dictionary<TextBlock, String>)e.Argument; 

     foreach (KeyValuePair<TextBlock, String> kvp in dic) 
     { 
      //i am unsure if this line will work. if it does not, you might need to do a separate dispatcher invoke in order to retreive the text from the textbox. 
      List<RunInfo> runinfoObjects = Syntax.Highlight(kvp.Value); 
      kvp.Key.Dispatcher.BeginInvoke(new Action(() => 
      { 
       kvp.Key.Inlines.Clear(); 
       //we'd run into problems here, since wpf won't allow us to add elements created in a background thread. since we now make the Run object inside the invoke, we should be fine. 
       runinfoObjects.ForEach(x => kvp.Key.Inlines.Add(x.AsRun())); 
      })); 
     } 
    } 
} 
+0

雖然 –

+0

我仍然收到相同的錯誤消息更新了答案。當在另一個線程中構建WPF元素時,無法將其添加到UI線程中。 –