Lets assume that I have a several layers:
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.
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.