在动态创建的多线程中维持参数值?(c#)
本文关键字:参数 创建 动态 多线程 | 更新日期: 2023-09-27 18:03:35
我不能说我完全理解线程的概念,即使我读了这么多的文章,我有点厚,我想要的是线程安全参数。我正在发送字符串参数到一个线程,我正在使用ThreadPool。QueueUserWorkItem开始,但我使用相同的线程之后,它再次与另一个参数。
我想从它能够处理不同的线程与不同的参数,但它不稳定可能是因为我正在改变参数字符串后调用第一个线程。直觉告诉我应该用Lock,但不知道怎么用,在哪里用。
哦,顺便说一句,这段代码的输出通常是3个线程使用最新的参数(这是配置为200p)
我用来调用线程的代码是:
processThread pt = new processThread();
pt.fileName = AppDomain.CurrentDomain.BaseDirectory + "bin''ffmpeg.exe";
pt.filePath = Path.Combine(Vci.Core.Sandbox.UploaderControlSandboxPath, fileGuid);
pt.vidPathHigh = AppDomain.CurrentDomain.BaseDirectory + "videos''480p''" + fileGuid + ".wmv";
pt.vidPathMid = AppDomain.CurrentDomain.BaseDirectory + "videos''360p''" + fileGuid + ".wmv";
pt.vidPathLow = AppDomain.CurrentDomain.BaseDirectory + "videos''200p''" + fileGuid + ".wmv";
if (height >= 480)
{
newHeight = (int)Math.Floor(480 * aspectRatio);
initArgs = "-i " + pt.filePath + " -vcodec wmv2 -qscale 2 -s " + newHeight + "x480 -acodec wmav2 -ar 44100 -ab 128k -y '"" + pt.vidPathHigh + "'"";
ThreadPool.QueueUserWorkItem(o => pt.callExecute(initArgs));
newHeight = (int)Math.Floor(360 * aspectRatio);
initArgs = "-i " + pt.filePath + " -vcodec wmv2 -qscale 4 -s " + newHeight + "x360 -acodec wmav2 -ar 44100 -ab 128k -y '"" + pt.vidPathMid + "'"";
ThreadPool.QueueUserWorkItem(o => pt.callExecute(initArgs));
newHeight = (int)Math.Floor(200 * aspectRatio);
initArgs = "-i " + pt.filePath + " -vcodec wmv2 -qscale 6 -s " + newHeight + "x200 -acodec wmav2 -ar 44100 -ab 128k -y '"" + pt.vidPathLow + "'"";
}
我的线程类的代码是这样的;
public class processThread
{
public string filePath { get; set; }
public string fileName { get; set; }
public string vidPathHigh { get; set; }
public string vidPathMid { get; set; }
public string vidPathLow { get; set; }
public void callExecute(Object o)
{
try
{
executeProcess(fileName, o as string);
}
catch (ThreadAbortException abortException)
{
// do something
}
}
private void executeProcess(string fileName, string arguments)
{
Process myProcess = new Process();
myProcess.StartInfo.FileName = fileName;
myProcess.StartInfo.Arguments = arguments;
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.CreateNoWindow = false;
myProcess.StartInfo.RedirectStandardOutput = false;
try
{
myProcess.Start();
}
catch (Exception ex)
{
throw;
}
myProcess.WaitForExit();
myProcess.Close();
}
}
提前感谢任何帮助是感激的!
问题是您正在通过使用lambda表达式"捕获"initargs
。
你不应该以这种方式重用initargs
。你的代码将更容易读,更容易维护,你将避免这个问题。
initargs
实例:
string initArgsWithScaleTwo = //
ThreadPool.QueueUserWorkItem(o => pt.callExecute(initArgsWithScaleTwo));
string initArgsWithScaleFour = //
ThreadPool.QueueUserWorkItem(o => pt.callExecute(initArgsWithScaleFour));
第二,当您分配给initArgs
时,有很多不必要的重复。维持这一点都不好玩。这应该会让你开始一个更清晰的版本:
private string GetInitArgs(
string filePath,
int scale,
int newHeight,
string vidPathHigh,
int scanLines
) {
return "-i " + filePath + String.Format(" -vcodec wmv2 -qscale {0} -s ", scale) + newHeight + String.Format("x{0} -acodec wmav2 -ar 44100 -ab 128k -y '"" + pt.vidPathHigh + "'"", scanLines);
}
你可以做更多,使用String.Format
来真正清理整个东西。
然后你可以说
string initArgsWithScaleTwoAnd480ScanLines =
GetInitArgs(
pt.filePath,
2,
(int)Math.Floor(480 * aspectRatio,
pt.vidPathHigh,
480
);
说了这么多,我不明白为什么你要使用线程,如果线程只是启动新的进程。直接启动进程,等待它们全部完成。
嗯,我不确定我是否明白你在问什么。Process.Start
通常不会阻塞当前线程,因此您可以启动尽可能多的新进程,因为您的系统可以从您的应用程序的单个线程中吞下…
我不确定initArgs
在哪里定义,所以改变它并调用使用它的线程可能会导致一些问题。
但是我建议你看看Joseph Albahari关于Threading的免费电子书。这是一个很好的资源,提供了一些关于如何为各种线程场景设计代码的好建议。在您的情况下,您可能需要考虑等待和脉冲模式。