0

Lets assume that I have a several layers:

  1. Manager that reads data from a socket
  2. Manager that subscribes to #1 and takes care about persisting the data
  3. Manager that subscribes to #2 and takes care about deserialization of the data and propagating it to typed managers that are insterested in certain event types
  4. WPF Controllers that display the data (are subscribed to #3)

As of right now I use

TaskFactory.StartNew(()=>subscriber.Publish(data)); 

on each layer. The reason for this is that I don't want to rely on the fact that every manager will do his work quickly and that ex. Socket manager is not stuck.

Is this a good approach?

Edit Let's say that Socket manager receives a price update There are 10 managers subscribed to Socket manager so when Socket manager propagates the message .StartNew is called 10 times.

Managers #2,#3 do nothing else but to propagate the message by .StartNew to a single subscriber

So ultimately per 1 message from socket 30x .StartNew() is called.

4

2 回答 2

1

这似乎是一个合理的方法。

但是,如果可以有意义地做:

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例如写入或读取数据库或文件系统,那么线程使用可以更好地扩展。

于 2015-06-20T23:54:36.960 回答
0

关于Task.Runvs. TaskFactory.StartNew,它们本质上是相同的。请阅读以下链接:http: //blogs.msdn.com/b/pfxteam/archive/2014/12/12/10229468.aspx

即使这些方法使用 ThreadPool 来获得不错的性能,也存在与不断创建新任务相关的开销。Task通常更多地用于不频繁的、即发即弃类型的工作负载。您关于“来自套接字的每 1 条消息 30x”的说法.StartNew()有点令人担忧。套接字消息多久到达一次?如果您真的关心延迟,我认为更好的方法是每个管理器都应该有自己的专用线程。您可以使用 BlockingQueue 实现,以便线程等待使用父队列中的父输入项。例如,这比简单的自旋锁更可取。

这是金融市场消息订阅和解码中经常使用的那种架构,需要尽可能快的性能。还要记住,更多的线程并不总是等同于更快的性能。如果线程有任何共享数据依赖关系,它们都将争用相同的锁,从而导致彼此之间的上下文切换等。这就是为什么预设数量的专用线程通常可以胜过在其上创建的更多线程的原因-苍蝇。我能想到的唯一例外是完全没有共享数据依赖关系的“令人尴尬的并行”任务。请注意,输入端和输出端都可能存在依赖关系(lock线程可能遇到的任何地方)。

于 2015-06-20T21:27:22.167 回答