Как обрабатывать позиции в очереди, серийно на низкой приоритетной ните с использованием параллельных расширений

StackOverflow https://stackoverflow.com/questions/4252634

Вопрос

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

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

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, но это не гарантирует, что они будут спасены по порядку и могут также представить утверждение с записью в файл.

Это было полезно?

Решение

Я бы предложил создать 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, поэтому я не мог сказать.

Другие советы

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

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

Вы буквально описываете корпус использования для фонда рабочего процесса - все это делает для вас все эти вещи :)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top