在动态创建的多线程中维持参数值? (C#)
我不能说我完全理解线程的概念,即使我读了很多关于它的文章,我有点厚,我想要的是线程安全参数。我正在将字符串参数发送到一个线程,我正在使用 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();
}
}
预先感谢任何帮助!
I can't say i fully understood the concept of threads even i read so many articles over it, i'm a bit thick and what i want is thread safe parameters. I'm sending string arguments to a thread that i'm using ThreadPool.QueueUserWorkItem to start but i'm using the same thread just after it again with another arguments.
What i want from it to be able to process different threads with different arguments but its not stable probably because i'm changing the parameter string just after calling the first thread. My instincts tell me to use Lock but don't know how to and where..
Oh btw the output of this code is usually 3 threads working with the latest parameter (which is configurations for 200p)
The code i use to call my thread is this;
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 + "\"";
}
And code to my thread Class is this;
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();
}
}
Thanks in advance any help is appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
问题是您正在通过使用 lambda 表达式“捕获”
initargs
。您不应该以这种方式重用
initargs
。您的代码将更具可读性且更易于维护,并且您将避免此问题。因此,首先,使用两个不同的
initargs
实例:其次,当您分配给
initArgs
时,会出现大量不必要的重复。维护起来并不有趣。这应该让您开始使用更清晰的版本:您可以做更多事情并使用 String.Format 来真正清理整个事情。
那么你可以说,
综上所述,如果线程只是启动新进程,我根本不明白你为什么要使用线程。只需直接启动进程,然后等待它们全部完成即可。
The issue is that you are "capturing"
initargs
via the use of the lambda expression.You shouldn't be reusing
initargs
in this way. Your code will be more readable and easier to maintain, and you will avoid this problem.So, first, use two different instances of
initargs
:Second, there's a lot of needless repetition when you assign to
initArgs
. That's not fun to maintain. This should get you started on a clearer version:You can do more and use
String.Format
to really clean the whole thing up.Then you can say
All that said, I don't understand why you are using threads at all if the threads are merely starting new processes. Just start the processes directly, and wait for them all to finish.
嗯,我不确定我是否明白你在问什么。 Process.Start 通常不会阻塞当前线程,因此您可以启动尽可能多的新进程,因为您的系统可以从应用程序的单个线程中吞下...
Hm, I am not sure if I understand what you are asking.
Process.Start
normally does not block current thread, so you can start as many new processes as your system can swallow from single thread of your application...我不确定 initArgs 的定义位置,因此更改它并调用使用它的线程可能会导致一些问题。
但我建议您查看 Joseph Albahari 关于线程的免费电子书。这是一个很好的资源,并提供了一些关于如何为各种线程场景设计代码的好建议。对于您的情况,您可能需要考虑等待和脉冲模式。
I'm not sure where
initArgs
is defined, so changing that and calling threads which use it could lead to some problems.But I'd recommend you look at Joseph Albahari's free e-book on Threading. It's an excellent resource and provides some good suggestions on how to design your code for various threading scenarios. In your case, you may want to consider the Wait and Pulse pattern.