簡體   English   中英

C#,WPF->在BackgroundWorker中更新時,GUI不應凍結

[英]C#, WPF -> GUI should not freeze while Updating in 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));
                }));
            }

        }
    }

語法高亮:

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並避免凍結? 看到它如何堆積是沒有問題的,只是凍結是個問題。

希望任何人都知道如何解決此問題。

您可以像這樣將大量工作移至調用之外:

一個小警告:我不確定您如何檢索文本框的文本。 您可能需要為此單獨進行調用(請參見代碼中的注釋)

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()));
            }));
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM