首页 > 解决方案 > WPF 文本框更改直到所有处理完成后才会呈现

问题描述

我正在使用 WPF,并希望它像控制台应用程序一样工作。请多多包涵,因为这是我第一次尝试使用 WPF。基本上我现在拥有的是一个全屏的白色窗口,里面有一个文本框。

我有一个调用方法的 ContentRendered 事件。这种方法需要做一些进程(包括启动和杀死一些应用程序)。在每个进程和另一个进程之间,它正在更改 textBox.Text 并附加状态,类似于“Process x ready ...”等。

我遇到的问题是窗口正在加载一个空的文本框,并且在所有进程都准备好之后, textBox.Text 更改都在最后立即呈现。

我究竟做错了什么?

public partial class MainWindow : Window
{
    public MainWindow()
    {
        Topmost = true;
        InitializeComponent();
    }

    private async void Window_ContentRendered(object sender, System.EventArgs e)
    {
        await ProcessFlow.Start();
    }
}


class ProcessFlow
{
    public async static Task Start()
    {
        await Logger.Write("Opening App...");

        ProcessStartInfo startInfo = new ProcessStartInfo(@"C:\Program Files (x86)\App\App.exe");
        startInfo.WindowStyle = ProcessWindowStyle.Hidden;

        using (var process = Process.Start(startInfo))
        {
            await Logger.WriteLine(" done!");
            Thread.Sleep(30000);
            await Logger.Write("Closing App...");
            process.Kill();
            await Logger.WriteLine(" done!");
        }
    }
}


public class Logger
{
    static MainWindow Form = Application.Current.Windows[0] as MainWindow;

    public async static Task Write(string text)
    {
        Form.textBox1.Text += text;
    }

    public async static Task WriteLine(string text)
    {
        Form.textBox1.Text += text + "\r\n";
    }
}

标签: c#.netwpf

解决方案


尝试这个。

使用 Task.Run() 在后台线程中完成工作。

由于现在在非 UI 线程上调用 Logger 方法,因此需要额外的工作来将调用编组回 UI 线程,因此我们使用 Dispatcher.InvokeAsync()。

public partial class MainWindow : Window
{
    Logger logger;

    public MainWindow()
    {
        InitializeComponent();

        logger = new Logger(this);
    }

    private async void Window_ContentRendered(object sender, EventArgs e)
    {
        ProcessFlow processFlow = new ProcessFlow(logger);

        await processFlow.Start();
    }
}

class ProcessFlow
{
    private readonly Logger logger;

    public ProcessFlow(Logger logger)
    {
        this.logger = logger;
    }

    public Task Start()
    {
        return Task.Run(
            async () =>
            {
                await logger.Write("Opening App...");

                ProcessStartInfo startInfo = new ProcessStartInfo(@"notepad.exe")
                {
                    UseShellExecute = true
                };

                // startInfo.WindowStyle = ProcessWindowStyle.Hidden;

                using (var process = Process.Start(startInfo))
                {
                    await logger.WriteLine(" done!");
                    await Task.Delay(2000);
                    await logger.Write("Closing App...");
                    process.Kill();
                    await logger.WriteLine(" done!");
                }       
            }
        );
    }
}

public class Logger
{
    private readonly MainWindow window;

    public Logger(MainWindow window)
    {
        this.window = window;
    }

    public Task Write(string text)
    {
        return window.Dispatcher.InvokeAsync(() => window.textBox1.Text += text).Task;
    }

    public Task WriteLine(string text)
    {
        return window.Dispatcher.InvokeAsync(() => window.textBox1.Text += text + "\r\n").Task;
    }
}

推荐阅读