Search code examples
c#wpftasktaskfactory

Is it a good practice to use TaskFactory.StartNew for every layer in push model?


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.


Solution

  • It seems a reasonable approach.

    However, if one could meaningfully do:

    subscriber.PublishAsync(data).LogExceptions(Log);
    

    Where LogExceptions is something like:

    // 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);
      }
    }
    

    So that fire-and-forget use of tasks still have errors logged, and PublishAsync in turn makes use of tasks where appropriate, then I'd be happier still. In particular, if the "publishing" has anything that would block a thread that can be handled with async like writing to or reading from a database or file system then the thread use could scale better.