1

我想知道使用.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));
}

想到的一个选择是将它们添加到 aQueue并让 aTimer处理它们。但这并没有利用远程调用的停机时间。

想到的另一个选择是使用System.Threading.Tasks.Taskper将每个结果异步写入文件Step,但这并不能保证它们会按顺序保存,并且还可能会引入写入文件的争用。

4

3 回答 3

1

我建议创建一个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 还不是很熟悉,所以我不能说。

于 2010-11-23T05:07:13.847 回答
1

一种方法是创建自定义任务计划程序(请参阅http://msdn.microsoft.com/en-us/library/ee789351.aspx)。您的自定义任务调度程序可以将并发限制为一次一个,并强制执行严格的按顺序执行。

创建任务调度程序还允许您控制线程优先级,或在某些情况下可能需要的 ApartmentState。

于 2010-11-24T23:58:49.403 回答
0

您实际上是在描述 Workflow Foundation 的用例 - 它为您完成所有这些工作:)

于 2010-11-23T08:02:57.727 回答