параллельное программирование в .net 4.0 - PullRequest
0 голосов
/ 31 марта 2011

Я читал о параллельном программировании и даже сейчас все еще немного запутался в концепциях. Допустим, у меня есть один проект с примерно 5 классами, которые взаимодействуют и имеют локальные переменные в методах и переменные, доступные для всех методов в одном классе, и даже 1 или 2 переменные, доступные для всех классов, доступ к которым осуществляется посредством создания экземпляров. Теперь, используя потоки, я знаю, что глобальные переменные будут переопределены несколькими потоками, если не будет применена блокировка, а локальные переменные для метода / функции - нет, верно? Так что, если бы я запустил проект несколько раз, имея в виду, что это новый процесс, методы и переменные были бы безопасны для потоков, и повреждение данных не произошло? Поэтому для реализации параллельного программирования с использованием фабрики задач, если я создал проект, который в основном создает задачи, и каждая задача в основном выполняет экземпляр другого проекта, то не должны ли переменные и данные быть потокобезопасными и защищенными от повреждения? Но что, если бы у меня были выходные файлы и они назывались Output & datetime.now.tostring, возникли бы проблемы с конфликтом, и я спрашиваю об этом, зная, что я видел, как это происходило при попытке сделать это.

dim factory as new taskfactory
factory.startnew(addressof projectinstance.main)

Теперь это может быть здравым смыслом для большинства из вас, поэтому будьте осторожны с критикой здесь, пожалуйста. спасибо ценим любой ответ.

EDIT:

Это модуль создания файлов в одном из классов:

Private Sub createXML()
    num += 1
    Dim fileList As New ArrayList
    Dim counter As Integer = 0
    Dim file As String = Module1.infile
    xmlfile = directoryPath & "\Feed" & DateTime.Now.ToUniversalTime.ToString("yyyyMMddhhmmss") & endExtension
    fileList.Add(xmlfile)
    Thread.Sleep(2000)
    Dim doc As XmlDocument = New XmlDocument
    xwriter = New XmlTextWriter(xmlfile, Encoding.UTF8)
    xwriter.Formatting = Formatting.Indented
    xwriter.Indentation = 2
    xwriter.WriteStartDocument(True)
    xwriter.WriteStartElement("Posts")
    Dim j As Integer = 0
    For i As Integer = 0 To gXmlList.Count() - 1
        j += 1
        parseXML(gXmlList(i))

....

1 Ответ

1 голос
/ 31 марта 2011

Это одна и та же программа, несколько данных шаблон SPMD .По сути, вы создаете отдельную программу или граф объектов для каждой задачи (задача в конечном итоге назначается в потоке).Экземпляры переменных, которые являются глобальными для графа объектов, будут хороши (поэтому не статические глобальные переменные), но все равно нужно будет беспокоиться об общих ресурсах, таких как файлы.

Одним из способов решения этих типов проблем является назначение каждому экземпляру задачи уникального идентификатора или «ранга» и использование его для определения ресурсов и присвоения им имен.В вашем примере файла каждая задача выдаст файл с именем myoutput_ {rank} .txt.Если то, что вы на самом деле хотите, это один файл, то ваше приложение должно реализовать этап постобработки, агрегации, в котором результаты объединяются.Это происходит последовательно после окончания параллелизма.Это как карта / уменьшить.Каждая из ваших параллельных задач запускает одну и ту же «программу» для сопоставления некоторых входных данных с выходным набором данных (файл в вашем случае), а затем на отдельном этапе вы уменьшаете или объединяете результаты в окончательный ответ.

Вот пример:

    static void Main()
    {
        const int maxJobs = 10;

        // Run jobs and wait...
        List<Task> tasks = new List<Task>();
        for (int rank = 0; rank < maxJobs; rank++)
            tasks.Add(Task.Factory.StartNew((r) => { new MyApp().Main((int)r); }, rank));

        Task.WaitAll(tasks.ToArray());

        // Aggregate results...
        StringBuilder sb = new StringBuilder();
        for (int rank = 0; rank < maxJobs; rank++)
            sb.AppendLine(File.ReadAllText("results_" + rank + ".txt"));

        Console.WriteLine(sb.ToString());
        File.WriteAllText("results_final.txt", sb.ToString());
        Console.ReadLine();
    }

    public class MyApp
    {
        public void Main(int rank)
        {
            Console.WriteLine("Starting {0}", rank);
            File.WriteAllText("results_" + rank + ".txt", "result data " + rank);
        }
    }

У класса MyApp может быть сколько угодно состояний.Он может даже совместно использовать это состояние с дочерними объектами, но он не должен иметь статического состояния или общего состояния с глобальными объектами, которые определены для чтения / записи вне MyApp.

Можно использовать глобальное состояние только для чтения.Например, все экземпляры MyApp могут считывать входные данные из одного файла.Что не в порядке, так это наличие нескольких экземпляров MyApp, читающих и , записывающих данные в (одну) глобальную переменную, экземпляр объекта или другой ресурс, например, файл, без реализации какой-либо формы координации (например, блокировки).

В приведенном выше примере каждая задача создает локальный файл results_ {rank} .txt.Их содержимое объединяется в один файл результатов, results_final.txt, на отдельном этапе агрегирования.Это невозможно сделать параллельно, потому что тогда все задачи будут записываться в один глобальный ресурс.

Многие из этих концепций описаны в книге, а примеры вы можете найти здесь.Контент также доступен (бесплатно) на MSDN.

http://parallelpatterns.codeplex.com/

...