C# 进程的信号量和多线程问题。启动
我不确定下面的代码有什么问题,但没有按预期工作。该设计允许用户从列表框中选择任意数量的输入文件,然后单击“执行”按钮,使用不同的输入文件启动相同的可执行文件。我将添加一个控件,允许用户指定并发进程的数量,但现在我将硬编码为3以进行测试。我的期望是每个可执行文件都将按顺序启动(尽管我知道它们可能不会以这种方式完成),并且一次只执行3个(尽管这个数字最终将由用户输入控件控制)。我希望在调用流程的函数中添加其他功能,即任务优先级、返回exitcode,但目前我无法使基本功能正常工作。我在这个网站和其他网站上找到了许多不同的代码,但仍然无法使用。以下是当前版本:C# 进程的信号量和多线程问题。启动,c#,multithreading,semaphore,C#,Multithreading,Semaphore,我不确定下面的代码有什么问题,但没有按预期工作。该设计允许用户从列表框中选择任意数量的输入文件,然后单击“执行”按钮,使用不同的输入文件启动相同的可执行文件。我将添加一个控件,允许用户指定并发进程的数量,但现在我将硬编码为3以进行测试。我的期望是每个可执行文件都将按顺序启动(尽管我知道它们可能不会以这种方式完成),并且一次只执行3个(尽管这个数字最终将由用户输入控件控制)。我希望在调用流程的函数中添加其他功能,即任务优先级、返回exitcode,但目前我无法使基本功能正常工作。我在这个网站和其他
private void btnParserExe_Click(object sender, EventArgs e)
{
Pool = new Semaphore(3,3); //Pool above declared as class variable
string ExeName = "C:\\Program Files (x86)\\Norman\\bin\\OC2.exe";
string Args;
string ArgDir = this.dirListBox1.Path + "\\";
for (int i = 0; i < this.fileListBox1.Items.Count; i++)
{
if (this.fileListBox1.GetSelected(i) == true)
{
Args = "-i " + this.fileListBox1.get_Items(i) + " -r -c -noerr";
Thread thread = new Thread(() => DoWork(ArgDir, ExeName, Args, "3"));
thread.Start();
}
}
}
private static void DoWork(string WorkingDir, string exefile, string parameters, string priority)
{
Pool.WaitOne();
Process exeProcess = new Process();
int exitCode;
try
{
exeProcess.StartInfo.FileName = exefile;
exeProcess.StartInfo.Arguments = parameters;
exeProcess.StartInfo.WorkingDirectory = WorkingDir;
exeProcess.Start();
exeProcess.WaitForExit();
}
catch (Exception ex)
{
MessageBox.Show("ERROR EXECUTING: " + parameters + " " + ex.Message);
}
finally
{
exitCode = exeProcess.ExitCode;
}
Pool.Release();
}
}
private void btnparserex\u单击(对象发送方,事件参数)
{
Pool=新信号量(3,3);//上面的Pool声明为类变量
string ExeName=“C:\\Program Files(x86)\\Norman\\bin\\OC2.exe”;
字符串参数;
字符串ArgDir=this.dirListBox1.Path+“\\”;
for(int i=0;iDoWork(ArgDir,ExeName,Args,“3”);
thread.Start();
}
}
}
私有静态void DoWork(字符串WorkingDir、字符串exefile、字符串参数、字符串优先级)
{
Pool.WaitOne();
进程exeProcess=新进程();
int exitCode;
尝试
{
exeProcess.StartInfo.FileName=exefile;
exeProcess.StartInfo.Arguments=参数;
exeProcess.StartInfo.WorkingDirectory=WorkingDir;
exeProcess.Start();
exeProcess.WaitForExit();
}
捕获(例外情况除外)
{
MessageBox.Show(“执行错误:“+parameters+”“+ex.Message”);
}
最后
{
exitCode=execprocess.exitCode;
}
Pool.Release();
}
}
我面临的三个主要问题:
Thread.Start()
sense中)快速连续启动时,可能会经历“第二个”线程,而实际上是在“第一个”线程之前开始执行。如果有序执行很重要,则需要序列化它们的执行(这似乎可以避免启动多个线程的需要).Net 4.0现在为简单的并行任务提供了一些新工具: 通过使用Parallel.For,您可以管理并发性,并且任务应该按顺序启动 在.NET2.0中,您可以使用一些后台工作人员和一个简单的控制器方法。比如:
Stack<string> filelist = new Stack<string>() {"file1", "file2"};
private void Setup()
{
System.ComponentModel.BackgroundWorker backgroundWorker1;
System.ComponentModel.BackgroundWorker backgroundWorker2;
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
backgroundWorker2.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
backgroundWorker2.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
}
private void Execute()
{
backgroundWorker1.DoWork();
backgroundWorker2.DoWork();
}
private string GetNextItem()
{
//this is a crude controller
return filelist.Pop();
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
// Get the BackgroundWorker that raised this event.
BackgroundWorker worker = sender as BackgroundWorker;
string nextFile = GetNextItem();
//Some simple check here to see if there were any items left or quit
....
//Now do work
Args = "-i " + nextFile + " -r -c -noerr";
DoWork(ArgDir, ExeName, Args, "3");
}
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Check for errors...
...
// See if more work to do
if (filelist.Count > 0)
{
//Repeat task
BackgroundWorker worker = sender as BackgroundWorker;
worker.DoWork();
}
}
Stack filelist=newstack(){“file1”、“file2”};
私有无效设置()
{
System.ComponentModel.BackgroundWorker backgroundWorker1;
System.ComponentModel.BackgroundWorker BackgroundWorker 2;
backgroundWorker1.DoWork+=新的DoworkerVenthandler(backgroundWorker_DoWork);
backgroundWorker1.RunWorkerCompleted+=新的RunWorkerCompletedEventHandler(backgroundWorker\u RunWorkerCompleted);
backgroundWorker2.DoWork+=新的DoworkerVenthandler(backgroundWorker_DoWork);
backgroundWorker2.RunWorkerCompleted+=新的RunWorkerCompletedEventHandler(backgroundWorker\u RunWorkerCompleted);
}
私有void Execute()
{
backgroundWorker1.dowwork();
backgroundWorker2.DoWork();
}
私有字符串GetNextItem()
{
//这是一个粗糙的控制器
返回filelist.Pop();
}
私有void backgroundWorker_DoWork(对象发送方,DoWorkEventArgs e)
{
//获取引发此事件的BackgroundWorker。
BackgroundWorker worker=发件人作为BackgroundWorker;
字符串nextFile=GetNextItem();
//在这里进行一些简单的检查,看看是否有任何项目剩余或退出
....
//现在开始工作
Args=“-i”+nextFile+”-r-c-noerr”;
DoWork(ArgDir,ExeName,Args,“3”);
}
私有void backgroundWorker_RunWorkerCompleted(对象发送方,runworkercompletedeventarge)
{
//检查错误。。。
...
//看看是否还有更多的工作要做
如果(filelist.Count>0)
{
//重复任务
BackgroundWorker worker=发件人作为BackgroundWorker;
工人。道工();
}
}
使用BackgroundWorkers,您还可以拥有独立的进度条等
代码未经测试。这些辅助进程是否重叠?如中所示,这三个进程在运行时是否会相互影响?如果不是,则有三个(或n个)线程访问单个GetNextWorkItem
Stack<string> filelist = new Stack<string>() {"file1", "file2"};
private void Setup()
{
System.ComponentModel.BackgroundWorker backgroundWorker1;
System.ComponentModel.BackgroundWorker backgroundWorker2;
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
backgroundWorker2.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
backgroundWorker2.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
}
private void Execute()
{
backgroundWorker1.DoWork();
backgroundWorker2.DoWork();
}
private string GetNextItem()
{
//this is a crude controller
return filelist.Pop();
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
// Get the BackgroundWorker that raised this event.
BackgroundWorker worker = sender as BackgroundWorker;
string nextFile = GetNextItem();
//Some simple check here to see if there were any items left or quit
....
//Now do work
Args = "-i " + nextFile + " -r -c -noerr";
DoWork(ArgDir, ExeName, Args, "3");
}
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Check for errors...
...
// See if more work to do
if (filelist.Count > 0)
{
//Repeat task
BackgroundWorker worker = sender as BackgroundWorker;
worker.DoWork();
}
}