我的程序需要一些帮助。我试图在选取框模式下显示进度条,当我的主线程(Form)启动一个新进程并等待进程退出时。这意味着我启动pdflatex来编译TEX文件,并使用progressbar显示新表单,直到进程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()方法。
非常感谢。
答案 0 :(得分: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();