Поддерживает значения параметров в нескольких потоках, которые создаются динамически? (С #) - PullRequest
2 голосов
/ 24 июля 2011

Не могу сказать, что полностью понял концепцию потоков, даже если прочитал так много статей, я немного толстый, и мне нужны параметры, обеспечивающие безопасность потоков.Я посылаю строковые аргументы потоку, который я использую 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();
    }
}

Заранее благодарен за любую помощь!

Ответы [ 3 ]

2 голосов
/ 24 июля 2011

Проблема в том, что вы "захватываете" 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
    );

Все это говорит, я не понимаю, зачем вы вообще используете потоки, если потоки просто запускают новые процессы. Просто запустите процессы напрямую и дождитесь их завершения.

0 голосов
/ 24 июля 2011

Я не уверен, где определено initArgs, поэтому изменение этого и вызов потоков, которые его используют, могут привести к некоторым проблемам.

Но я бы порекомендовал вам взглянуть на бесплатную электронную книгу Джозефа Албахари по теме Threading. Это отличный ресурс, который дает несколько хороших советов о том, как разработать свой код для различных сценариев многопоточности. В вашем случае вы можете рассмотреть шаблон Wait and Pulse .

0 голосов
/ 24 июля 2011

Хм, я не уверен, что понимаю, что вы спрашиваете. Process.Start обычно не блокирует текущий поток, поэтому вы можете запустить столько новых процессов, сколько ваша система может проглотить из одного потока вашего приложения ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...