问题描述
以下是相关代码:
Here is the relevant code:
public static ProcessStartInfo psi = new ProcessStartInfo(thecommand);
public static bool workerDone;
public frmMain()
{
InitializeComponent();
work1.DoWork += new DoWorkEventHandler(DoProcessing);
}
private void btnProcess_Click(object sender, EventArgs e)
{
foreach (string loop in fileNamesToProcess)
{
Prepare(loop, out thePath, out tempStr, out thecommand, out thearguments);
// DoProcessing();
psi.WindowStyle = ProcessWindowStyle.Minimized;
psi.Arguments = thearguments;
psi.FileName = thecommand;
workerCompleted = false;
BackgroundWorker work1 = new BackgroundWorker();
work1.DoWork += new DoWorkEventHandler(DoProcessing);
work1.RunWorkerCompleted += new RunWorkerCompletedEventHandler
(work1_RunWorkerCompleted);
work1.WorkerReportsProgress = true;
work1.RunWorkerAsync(psi);
// Wait for thread to finish
while (!workerCompleted)
{
}
// Delete the original
File.Delete(workFile);
// Rename the processed file
File.Move(outFile, workFile);
MoveToDoneList();
work1 = null;
}
}
private static void DoProcessing(object sender, DoWorkEventArgs e)
{
Process p = Process.Start(psi);
// Wait for it to finish processing before going on
while (!p.HasExited)
{
}
workerCompleted = true;
}
void work1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
workerCompleted = true;
}
进程p运行正常,workerDone设置为true,foreach循环继续进行,直到再次遇到work1.RunWorkerAsync()
,当我收到它仍然很忙且无法再次运行的错误.
使用BackgroundWorker是因为我的DoProcessing是DOS命令,并且我希望保持窗口活动"状态以能够执行Stop(但不能取消worker,只需停止继续进行下一个项目的foreach循环即可).
我看到一个问题,就是我的过程花了太长时间.需要发送偶尔的消息,但是我不能,因为通过声明work1我无法访问work1.ReprtProgress.也许我只需要放弃在线程中运行该进程,如果我想中断它,请使用任务管理器-无论如何我都可以使用.
Process p runs fine, workerDone is set to true, the foreach loop continues until work1.RunWorkerAsync()
is encountered again, when I get the error that it is still busy, and cannot be run again.
Using a BackgroundWorker because my DoProcessing is a DOS command and I want to keep my window "alive" to be able to do a Stop (but not cancel the worker, just stop the foreach loop going on to the next item.)
I see a problem in that my process takes too long. Needs to send the occasional message, but I can''t because by declaring the work1 where I do I can''t access work1.ReprtProgress. Maybe I''ll just have to forgo running the process in a thread and if I want to interrupt it, use task manager - is for my own use anyway.
推荐答案
/// <summary>
/// A class to pass as an argument to the DoWork method of the background
/// worker
/// </summary>
public class ProcessAudioStartArguments
{
/// <summary>
/// ctor
/// </summary>
/// <param name="files">List of file names to process</param>>
public ProcessAudioStartArguments(List<ProcessStartInfo> files)
{
this.FilesToProcess = files;
}
/// <summary>
/// The list of files to delete
/// </summary>
public List<ProcessStartInfo> FilesToProcess { get; private set; }
}
然后,您的实际代码应如下所示..
*建立参数列表以发送给后台工作者
*启动工作程序,传入我们的自定义参数对象
Your actual code should then look something like this..
* Build up a list of arguments to send to the background worker
* Start the worker, pass in our custom arguments object
private void btnProcess_Click(object sender, EventArgs e)
{
List<ProcessStartInfo> files = new List<ProcessStartInfo>();
// Prepare your arguments to send to the worker...
foreach (string loop in fileNamesToProcess)
{
Prepare(loop, out thePath, out tempStr, out thecommand, out thearguments);
ProcessStartInfo psi = new ProcessStartInfo();
psi.WindowStyle = ProcessWindowStyle.Minimized;
psi.Arguments = thearguments;
psi.FileName = thecommand;
files.Add(psi);
}
ProcessAudioStartArguments arguments = new ProcessAudioStartArguments(files);
audioWorker.RunWorkerAsync(arguments);
}
*在工作线程中执行所有处理.检查取消情况,报告进度等
* Do all processing in the worker thread. Check for cancellations, report on progress etc
private void audioWorker_DoWork(object sender, DoWorkEventArgs e)
{
ProcessAudioStartArguments arguments = (ProcessAudioStartArguments)e.Argument;
foreach(ProcessStartInfo psi in arguments.FilesToProcess)
{
if (audioWorker.CancellationPending)
break;
// Some sort of progress reporting...
var displayText = string.Format(Resources.ProcessingFile, Path.GetFileName(psi.FileName));
audioWorker.ReportProgress(step, displayText);
Process p = Process.Start(psi);
p.WaitForExit();
// Some sort of check for success? Return code of process?
// Delete the original
File.Delete(workFile);
// Rename the processed file
File.Move(outFile, workFile);
}
e.Result = someObj // Report on the success of the processing...?
}
处理进度报告...
Handle progress reporting...
void audioWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
string currentFile = e.UserState.ToString();
// Some sort of process window to display percentage done etc...
progressWindow.SetText(currentFile);
progressWindow.StepTo(e.ProgressPercentage);
}
因此,将所有工作留给后台工作人员,您只需将其启动一次,然后传递一个arguments对象即可为它提供完成工作所需的所有信息.
我在文章安全删除.NET [ ^ ].
HTH
So leave all the work to the background worker, you just start it once and pass in an arguments object that gives it all the information it requries to complete the job.
I do something similar in my article Secure Delete .NET[^].
HTH
这篇关于BackgroundWorker不会运行两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!