Как обрабатывать поставленные в очередь элементы последовательно в потоке с низким приоритетом, используя Parallel Extensions - PullRequest
1 голос
/ 23 ноября 2010

Я хочу знать, каков наилучший способ последовательной обработки результатов длительного процесса, но в потоке с низким приоритетом, с использованием .NET 4.0 Parallel Extensions .

У меня есть следующий класс, который выполняет и обеспечивает результаты:

public class Step 
{
  public string Name { get; set; }
  public TimeSpan Duration { get; set; }
  public bool Completed { get; set; }

  public void Execute() 
  {
     DateTime before = DateTime.Now;
     RemotedService.DoSomeStuff();
     Duration = DateTime.Now - before;
     Completed = true;
  }
}

Как я могу обработать эти шаги, а также сохранить их в файл, по порядку, после того, как ониобработанный?Я хотел бы сохранить их в файл, пока RemotedService.DoSomeStuff() ожидает ответа от сервера.

Запись в файл будет выглядеть следующим образом:

using (StreamWriter w = File.AppendText("myFile.txt"))
{
  var completedStep = completedSteps.Dequeue();
  w.WriteLine(string.Format("Completed {0} with result: {1} and duration {2}", 
                            completedStep.Name, 
                            completedStep.Completed, 
                            completedStep.Duration));
}

Один из возможных вариантовна ум стоит добавить их к Queue и иметь Timer, который их обрабатывает.Но это не использует время простоя удаленных вызовов.

Другой вариант, который приходит на ум, - это асинхронная запись каждого результата в файл с использованием System.Threading.Tasks.Task на Step, но это не так.Гарантируют, что они будут сохранены по порядку, а также могут привести к конфликту при записи в файл.

Ответы [ 3 ]

1 голос
/ 25 ноября 2010

Один из подходов заключается в создании настраиваемого планировщика заданий (см. http://msdn.microsoft.com/en-us/library/ee789351.aspx).. Настраиваемый планировщик заданий может ограничивать одновременность до одного за раз и обеспечивать строгое выполнение в порядке.

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

1 голос
/ 23 ноября 2010

Я бы предложил создать BlockingCollection<Step> (см. System.Collections.Concurrent пространство имен).По завершении каждого шага он добавляется в эту коллекцию.Поведение по умолчанию BlockingCollection состоит в том, чтобы функционировать как очередь, поэтому вы получите искомое поведение FIFO.

Второй поток обслуживает очередь, удаляя каждый элемент и записывая его в журнал.файл.

Итак, если вы добавили очередь:

static private BlockingCollection<Step> LogQueue = new BlockingCollection<Step>();

Вы добавили бы это к своему методу Execute, после того как элемент будет завершен:

LogQueue.Add(this);

И ваш поток журналирования, который вы бы начали в статическом конструкторе:

static void LoggingThread()
{
    using (var w = new StreamWriter(...))
    {
        while (!LogQueue.IsCompleted())
        {
            Step item;
            if (LogQueue.TryTake(out item))
            {
                w.WriteLine(....);
            }
        }
    }
}

Поток журналирования, как я уже писал, использует поток System.Threading.Там может быть более простой или лучший способ сделать это с TPL.Я еще не очень знаком с TPL, поэтому не могу сказать.

0 голосов
/ 23 ноября 2010

Вы буквально описываете сценарий использования для Workflow Foundation - он делает все это за вас:)

...