简体   繁体   中英

Wpf async await ui is frozen

I writing a WPF desktop application and I used async await to keep my UI update. its works OK for 5 or 6 sec but after that UI freezing but background code is running normally.

await Task.Run(() =>
{
    result = index.lucene_index(filepath, filename, fileContent);
    if (result) {
        updateResultTextBox(filename);
        Task.Delay(1000);
    }
});

and updateResultTextBox is

private void updateResultTextBox(string _filename)
{
    sync.Post(new SendOrPostCallback(o =>
    {
        result_tbx.Text += "Indexed \t" + (string)o + "\n";
        result_tbx.ScrollToEnd();
    }), _filename);
}

Your question is less then clear. So I have to guess. My only guess at this time: GUI write overhead.

Writing the GUI is not cheap. If you only do it once per user triggered event, you do not notice it. But once you do it in a loop - even one that runs in a seperate task or thread - you will notice it. I wrote this simple Windows Forms example to showcase the difference:

using System;
using System.Windows.Forms;

namespace UIWriteOverhead
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        int[] getNumbers(int upperLimit)
        {
            int[] ReturnValue = new int[upperLimit];

            for (int i = 0; i < ReturnValue.Length; i++)
                ReturnValue[i] = i;

            return ReturnValue;
        }

        void printWithBuffer(int[] Values)
        {
            textBox1.Text = "";
            string buffer = "";

            foreach (int Number in Values)
                buffer += Number.ToString() + Environment.NewLine;
            textBox1.Text = buffer;
        }

        void printDirectly(int[] Values){
            textBox1.Text = "";

            foreach (int Number in Values)
                textBox1.Text += Number.ToString() + Environment.NewLine;
        }

        private void btnPrintBuffer_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Generating Numbers");
            int[] temp = getNumbers(10000);
            MessageBox.Show("Printing with buffer");
            printWithBuffer(temp);
            MessageBox.Show("Printing done");
        }

        private void btnPrintDirect_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Generating Numbers");
            int[] temp = getNumbers(1000);
            MessageBox.Show("Printing directly");
            printDirectly(temp);
            MessageBox.Show("Printing done");
        }
    }
}

If you start a lot of those tasks and they suddenly all return 5-6 seconds in the process, you might just plain overload the GUI thread with the sheer amount of write operations.

I actually had that issue with my very first attempt at Multithreading. I did proper Multthreading, but I still overloaded the GUI thread wich made it appear I had failed.

there is something very strange on this code. Anyway, here are my two cents:

var text = await Task.Run(() =>
{
    result = index.lucene_index(filepath, filename, fileContent);
    if (result) {
        return filename;
    }
    return string.Empty;
});
if (!string.IsNullOrEmpty(text)) {
    result_tbx.Text += $"Indexed \t {text} {Environment.NewLine}";
    result_tbx.ScrollToEnd();
}

Still a code smell...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM