1

我的程序需要一点帮助。我试图在选取框模式下显示进度条,当我的主线程(表单)启动一个新进程并等待进程退出时。这意味着我启动 pdflatex 来编译 TEX 文件,并显示带有进度条的新表单,直到过程 WaitForExit() 方法完成。而且我需要知道我是否以正确的方式做这件事,或者还有另一种更好的方法。我有一个名为 Progress 的类,它扩展了 Form 并用于新线程。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;
using System.Drawing;

namespace Measuring
{
public class Progress : Form
{
    public Progress(Form form)
    {
        InitializeComponent(form);
    }

    private void InitializeComponent(Form parent)
    {
        this.FormBorderStyle = FormBorderStyle.None;
        this.Font = parent.Font;
        this.Size = new Size(300, 40);
        this.StartPosition = FormStartPosition.Manual;
        this.Location = new Point(parent.Left + ((parent.Width - this.Width) / 2), (parent.Top + ((parent.Height - this.Height) / 2)));

        ProgressBar progressbar = new ProgressBar();
        Label label = new Label();

        label.AutoSize = true;
        label.Text = "Converting file to pdf";
        label.Dock = DockStyle.Top;          

        progressbar.Dock = DockStyle.Bottom;
        progressbar.Maximum = 100;
        progressbar.Minimum = 0;

        progressbar.ForeColor = Color.Green;
        progressbar.Style = ProgressBarStyle.Marquee;
        progressbar.MarqueeAnimationSpeed = 10;


        this.Controls.Add(label);
        this.Controls.Add(progressbar);
    }

    public void Start()
    {
        this.ShowDialog();
    }

    public void Stop()
    {
        this.Close();
    }
}
}

现在我有streamwrite方法,最后我称之为:

        Process p = new Process();
        p.StartInfo.FileName = "pdflatex";
        p.StartInfo.Arguments = save.FileName;
        p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

        Progress prg = new Progress(this);
        Thread t = new Thread(prg.Start);

        try
        {

            if (p.Start())
            {
                t.Start();
                p.WaitForExit();
                prg.Stop();
                if (p.ExitCode != 0)
                {
                    MessageBox.Show("Conversion to pdf using LaTeX failed!" + Environment.NewLine + "No output file produced.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
        catch
        {
            MessageBox.Show("Pdflatex is not installed!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

似乎还可以,但我不知道它是否真的安全。我知道所有异常都没有得到处理,但主要是 Start() 和 Stop() 方法。

非常感谢。

4

1 回答 1

2

所以这里有几个问题。首先,您正在创建多个 UI 线程;您正试图在不同的线程中显示另一种形式。那是……几乎总是错的。它很难使用,并且底层框架通常假设只有一个 UI 线程,因此它可能会导致其他功能操作中的错误。

而是在 UI 线程之外进行非 UI 工作,因此 UI 线程(唯一的 UI 线程)可以自由地继续处理 UI 事件。

这很简单;事实上,我们甚至根本不需要创建另一个线程。该类Process已经提供了一个事件,该事件将在进程退出时触发。我们可以只为该事件添加一个处理程序,然后在 UI 线程中根本不等待任何东西;我们可以让它继续处理 UI 事件。

唯一剩下的问题是Exited事件处理程序将从线程池线程而不是 UI 线程触发,因此我们需要使用Invoke在 UI 线程中运行一些代码。

Process p = new Process();
p.StartInfo.FileName = "pdflatex";
p.StartInfo.Arguments = save.FileName;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.EnableRaisingEvents = true;
p.Exited += (sender, arguments) =>
{
    prg.Invoke(new Action(() => prg.Stop()));
    //TODO look at the process's status - display errors
};
prg.Start();
于 2013-11-06T21:27:19.023 回答