我需要连续几次启动外部程序,但我有几个问题:
这是代码(抱歉,它有点长):
private struct svnCommand
{
public svnCommand(string args, string path, int pourcent)
{
this.args = args;
this.path = path;
this.pourcent = pourcent;
}
public string args;
public string path;
public int pourcent;
}
private BackgroundWorker bgwkSVN;
public Merger()
{
InitializeComponent();
InitializeBackgroundWorker();
this.textBoxCheminRacine.Text = cheminRacine;
}
private void MergerRevisions(object sender, EventArgs e)
{
activerControles(false);
textBoxOutput.Text = "";
cheminRacine = textBoxCheminRacine.Text;
if (!cheminRacine.EndsWith("\\")) { cheminRacine = cheminRacine + "\\"; }
string branchToMerge = this.textBoxBranche.Text;
if (branchToMerge.StartsWith("/")) { branchToMerge = branchToMerge.Substring(1); }
// révision(s)
string revisions = "";
foreach (string r in textBoxRevision.Text.Split(','))
{
int rev;
if (int.TryParse(r, out rev))
{
revisions += string.Format(" -r {0}:{1}", rev - 1, rev);
}
else
{
revisions += " -r " + r.Replace("-", ":");
}
}
// pourcentage de complétion pour chaque étape
int stepPourcent = (int)Math.Floor((double)(100 / (3 + Directory.GetDirectories(cheminRacine + "branches").Length)));
// merge sur le trunk
while (bgwkSVN.IsBusy) { }
bgwkSVN.RunWorkerAsync(new svnCommand(string.Format("merge --accept postpone {0} {1}{2} .", revisions, svnbasepath, branchToMerge), cheminRacine + "trunk", stepPourcent));
// merge sur chaque branche
string[] branches = Directory.GetDirectories(cheminRacine + "branches");
foreach (string b in branches)
{
while (bgwkSVN.IsBusy) { }
bgwkSVN.RunWorkerAsync(new svnCommand(string.Format("merge --accept postpone {0} {1}{2} .", revisions, svnbasepath, branchToMerge), b, stepPourcent));
}
// virer les mergeinfo
while (bgwkSVN.IsBusy) { }
bgwkSVN.RunWorkerAsync(new svnCommand("pd svn:mergeinfo . -R", cheminRacine, stepPourcent));
// svn update
while (bgwkSVN.IsBusy) { }
bgwkSVN.RunWorkerAsync(new svnCommand("update", cheminRacine, stepPourcent));
textBoxOutput.Text += Environment.NewLine + "Terminé.";
MessageBox.Show("Merge terminé.", "Merge terminé", MessageBoxButtons.OK);
// réactiver les champs et boutons
activerControles(true);
}
/// <summary>
/// Set up the BackgroundWorker object by attaching event handlers
/// </summary>
private void InitializeBackgroundWorker()
{
bgwkSVN = new BackgroundWorker();
bgwkSVN.WorkerReportsProgress = true;
bgwkSVN.WorkerSupportsCancellation = true;
bgwkSVN.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
bgwkSVN.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
bgwkSVN.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
}
/// <summary>
/// Exécuter une commande SVN
/// </summary>
private string SVNcmd(svnCommand s, BackgroundWorker worker, DoWorkEventArgs e)
{
string o = "";
o += s.path + Environment.NewLine + s.args + Environment.NewLine;
if (worker.CancellationPending)
{
e.Cancel = true;
}
else
{
Process p = new Process();
p.StartInfo.WorkingDirectory = s.path;
p.StartInfo.FileName = "svn";
p.StartInfo.Arguments = s.args;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.Start();
o += p.StandardOutput.ReadToEnd() + Environment.NewLine;
p.WaitForExit();
if (s.pourcent > 0)
{
worker.ReportProgress(s.pourcent);
}
}
return o;
}
/// <summary>
/// Where the actual, potentially time-consuming work is done.
/// </summary>
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// Get the BackgroundWorker that raised this event.
BackgroundWorker worker = sender as BackgroundWorker;
// Assign the result of the computation to the Result property of the DoWorkEventArgs
// object. This is will be available to the RunWorkerCompleted eventhandler.
e.Result = SVNcmd((svnCommand)e.Argument, worker, e);
}
/// <summary>
/// Deals with the results of the background operation
/// </summary>
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// First, handle the case where an exception was thrown.
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
textBoxOutput.Text += Environment.NewLine + "Annulé.";
}
else
{
textBoxOutput.Text += e.Result.ToString();
}
}
/// <summary>
/// Updates the progress bar
/// </summary>
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.progressBarTraitement.Value += e.ProgressPercentage;
}
Run Code Online (Sandbox Code Playgroud)
谢谢 !
解决方案很简单:让一个BGW执行所有命令,而不是每个命令只执行一个BGW.您需要一个List<svnCommand>存储命令,以便您可以轻松地将它们传递给RunWorkerAsync().DoWork()可以简单地使用foreach迭代列表.
所以 nobugz 已经为您提供了正确的方向,但为了完整起见,这里有一些示例代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
namespace Threading
{
public partial class FormMain : Form
{
private BackgroundWorker _BackgroundWorker;
private Queue<Func<string>> _Commands;
private Random _Random;
public FormMain()
{
InitializeComponent();
_Random = new Random();
_Commands = new Queue<Func<string>>();
_BackgroundWorker = new BackgroundWorker();
_BackgroundWorker.WorkerReportsProgress = true;
_BackgroundWorker.WorkerSupportsCancellation = true;
_BackgroundWorker.DoWork += backgroundWorker_DoWork;
_BackgroundWorker.ProgressChanged += backgroundWorker_ProgressChanged;
_BackgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
_BackgroundWorker.RunWorkerAsync();
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
while (!_BackgroundWorker.CancellationPending)
{
if (_Commands.Count > 0)
{
AddMessage("Starting waiting job...");
AddMessage(_Commands.Dequeue().Invoke());
}
Thread.Sleep(1);
}
}
void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar.Value = e.ProgressPercentage;
}
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
AddMessage("BackgroundWorker doesn't make any further jobs.");
}
private void buttonStart_Click(object sender, EventArgs e)
{
_Commands.Enqueue(DoSomething);
//or maybe with a lambda
//_Commands.Enqueue(new Func<string>(() =>
//{
// string message;
// message = DoSomething();
// return message;
//}));
}
private string DoSomething()
{
int max = 10;
for (int i = 1; i <= max; i++)
{
Thread.Sleep(_Random.Next(10, 1000));
if (_BackgroundWorker.CancellationPending)
{
return "Job aborted!";
}
AddMessage(String.Format("Currently working on item {0} of {1}", i, max));
_BackgroundWorker.ReportProgress((i*100)/max);
}
return "Job is done.";
}
private void AddMessage(string message)
{
if (textBoxOutput.InvokeRequired)
{
textBoxOutput.BeginInvoke(new Action<string>(AddMessageInternal), message);
}
else
{
AddMessageInternal(message);
}
}
private void AddMessageInternal(string message)
{
textBoxOutput.AppendText(String.Format("{0:G} {1}{2}", DateTime.Now, message, Environment.NewLine));
textBoxOutput.SelectionStart = textBoxOutput.Text.Length;
textBoxOutput.ScrollToCaret();
}
private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
{
if (_BackgroundWorker.IsBusy)
{
_BackgroundWorker.CancelAsync();
e.Cancel = true;
AddMessage("Please close only if all jobs are done...");
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5651 次 |
| 最近记录: |