我想知道使用.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
将每个结果异步写入文件,但这并不能保证它们会按顺序保存并可能引入争用写入文件。
答案 0 :(得分: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,所以我不能说。
答案 1 :(得分:1)
一种方法是创建自定义任务计划程序(请参阅http://msdn.microsoft.com/en-us/library/ee789351.aspx)。您的自定义任务调度程序可以将并发限制为一次一个并强制执行严格的有序执行。
创建任务计划程序还允许您控制线程优先级,或者在某些情况下可能需要的ApartmentState。
答案 2 :(得分:0)
你真的在描述Workflow Foundation的用例 - 它为你做了所有这些事情:)