对推式模型中的每个图层使用TaskFactory.StartNew是否是一种很好的做法?
让我们假设我有几个层次:对推式模型中的每个图层使用TaskFactory.StartNew是否是一种很好的做法?
- 经理从套接字读取数据
- 经理订阅了#1和大约需要持续的数据
- 经理订阅了#2和护理需要关心的数据的反序列化和传播为键入了在某些事件类型
- WPF控制器,显示数据insterested管理者(订阅#3)
截至目前我使用
TaskFactory.StartNew(()=>subscriber.Publish(data));
在每一层上。原因是我不想想要依靠这样一个事实,即每个经理都会尽快完成他的工作,套接字管理器没有卡住。
这是一个很好的方法吗?
编辑 假设插槽管理器接收价格更新 有10个管理者订阅插槽经理,所以当插座管理者传播.StartNew被称为10倍的消息。
管理者#2,#3什么也不做,但可以通过.StartNew消息每1个消息,以便最终从插座30倍.StartNew传播到单个订户
()被调用。
这似乎是一个合理的方法。
然而,如果能够真正做到:
subscriber.PublishAsync(data).LogExceptions(Log);
哪里LogExceptions
是一样的东西:
// I'm thinking of Log4Net here, but of course something else could be used.
public static Task LogExceptions(this Task task, ILog log)
{
return task.ContinueWith(ta => LogFailedTask(ta, log), TaskContinuationOptions.OnlyOnFaulted);
}
private static void LogFailedTask(Task ta, ILog log)
{
var aggEx = ta.Exception;
if(aggEx != null)
{
log.Error("Error in asynchronous event");
int errCount = 0;
foreach(var ex in aggEx.InnerExceptions)
log.Error("Asynchronous error " + ++errCount, ex);
}
}
使发射后不管任务的使用还是有记录的错误,并PublishAsync
在转而在适当的时候使用任务,那么我会更开心。特别是,如果“发布”有任何东西会阻塞可以使用async
进行处理的线程,就像写入数据库或文件系统或从数据库或文件系统读取数据一样,那么线程的使用可能会更好地扩展。
关于Task.Run
与TaskFactory.StartNew
,它们在引擎盖下基本相同。请阅读以下链接:http://blogs.msdn.com/b/pfxteam/archive/2014/12/12/10229468.aspx
尽管这些方法使用ThreadPool来提供良好的性能,但仍然存在与不断创建新任务相关的开销。 Task
通常更多用于不经常发生的,即发即忘型的工作负载。你的声明是“来自套接字每1条消息的30x.StartNew()
”有点关注。套接字消息多久出现一次?如果你真的关心延迟,我认为这样做的更好方式是每个经理都应该有自己的专用线程。您可以使用BlockingQueue实现,以便线程正在等待消耗父队列中的父输入项。例如,这比简单的自旋锁更可取。
这是一种在金融市场消息订阅和解码中经常使用的架构,需要尽可能快的性能。另外请记住,更多的线程并不总是等同于更快的性能。如果线程具有任何共享数据依赖性,则它们将全部争用相同的锁,导致彼此之间的上下文切换等。这就是为什么预设数量的专用线程通常可以胜出,而线程创建的线程数量更多-the飞。我能想到的唯一例外就是没有共享数据依赖性的“令人尴尬的并行”任务。请注意,依赖关系可以存在于输入端和输出端(线程可能会遇到的lock
任何地方)。
现在很难相信在WPF应用程序中创建30个对象会成为问题。它更难相信你会实现一个更好的算法来管理自己的脚步比线程池经理会。 – Bond
这一切都取决于应用程序的延迟要求。 OP建议套接字监听器可能会收到*价格更新*消息,这表明他可能正在编写一个应用程序,用于监听交换(金融市场)消息。这样的流可以分解1000个信息/秒。在这种情况下,低延迟可能是非常重要的业务需求。正如我已经写了大约十几个低延时交换连接器,我可以肯定地说,在这种情况下,专用线程是最好的选择。如果我开发了一系列级联任务的解决方案,我会被解雇。 –
多线程肯定没有内在的错误。你能详细说明你的具体问题吗?总共有多少'.StartNew()'行可以同时运行? –
为什么不使用Task.Run()? – Transcendent
@Intercendent为什么要使用它? http://stackoverflow.com/questions/22087005/task-factory-startnew-vs-new-task此链接暗示否则 –