Возможны непреднамеренные последствия вашего подхода, поскольку механизм ASP.NET и библиотека параллельных задач - это задачи планирования в пуле потоков .NET. Каждый веб-запрос обслуживается потоком из пула потоков. Если вы планируете Задачи для обработки журналов, то вы будете использовать задачи в пуле потоков, которые больше не могут использоваться для обслуживания веб-запросов. Это может снизить пропускную способность.
Команда TPL написала об этом здесь.
http://blogs.msdn.com/b/pfxteam/archive/2010/02/08/9960003.aspx
Шаблон производитель / потребитель будет означать, что ваш метод MethodInterceptionAspect просто добавит запись в глобальную очередь (как предложил Бен), и тогда у вас будет одна (длительная) задача, которая обработает все записи. Таким образом, ваш метод пересечения становится:
ConcurrentQueue<TimeSpan> _queue;
public override void OnInvoke(MethodInterceptionArgs args)
{
var startDtg = DateTime.Now;
args.Proceed();
var duration = DateTime.Now - startDtg;
Task.Factory.StartNew(() => _queue.Add(duration));
}
Где-то еще вы обрабатываете очередь:
foreach (var d in _queue.GetConsumingEnumerable())
{
Console.WriteLine(d);
}
В следующем посте показана аналогичная реализация, в которой несколько задач, созданных в цикле Parallel.For, добавляют изображения в коллекцию BlockingCollection, а одна задача обрабатывает изображения.
Библиотека параллельных задач WaitAny Design
Насколько хорошо это работает, в некоторой степени зависит от длительности обработки вашего запроса, количества записей в журнале, которые вы хотите обработать за запрос, и общей нагрузки на сервер и т. Д. Одна вещь, о которой вы должны знать, это то, что в целом вам нужно иметь возможность удалять запросы из очереди быстрее, чем они добавляются.
Задумывались ли вы о подходе, когда вы пишете свой собственный счетчик производительности, и инфраструктура счетчика производительности справляется с этим? Это избавит вас от необходимости реализовывать любую из этих инфраструктур записи.