【问题标题】:Wpf async await ui is frozenWpf async await ui被冻结
【发布时间】:2018-02-02 21:30:37
【问题描述】:

我编写了一个 WPF 桌面应用程序,并使用 async await 来保持我的 UI 更新。 它可以正常工作 5 或 6 秒,但之后 UI 冻结但后台代码运行正常。

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

而 updateResultTextBox 是

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

【问题讨论】:

标签: c# wpf multithreading async-await


【解决方案1】:

您的问题不太清楚。所以我不得不猜测。目前我唯一的猜测是:GUI 写入开销。

编写 GUI 并不便宜。如果您只为每个用户触发的事件执行一次,您不会注意到它。但是一旦你在一个循环中执行它——即使是在一个单独的任务或线程中运行——你会注意到它。我编写了这个简单的 Windows 窗体示例来展示差异:

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

如果您启动了很多这样的任务,并且它们在此过程中突然全部返回 5-6 秒,那么您可能只是用大量的写入操作使 GUI 线程过载。

我第一次尝试多线程时就遇到了这个问题。我做了适当的多线程处理,但我仍然重载了 GUI 线程,这让它看起来我失败了。

【讨论】:

    【解决方案2】:

    这段代码有一些很奇怪的地方。无论如何,这是我的两分钱:

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

    仍然是代码味道...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-13
      • 2015-01-16
      • 2016-06-13
      • 2012-06-11
      相关资源
      最近更新 更多