У меня есть два решения, счетчики Peformance и в пользовательское поведение, но я не уверен, что если они точно отвечают на ваш вопрос, потому что я не учитываю сетевую задержку.
Счетчики производительности
Первый soltuion использует встроенный в performance counters, которая приближается к вашему требованию. В основном вы хотите включить PerformanceCounters для своего сервиса, а затем в своем сервисе получить один из них. Точная продолжительность недоступна, но Calls per second
входит в число других счетчиков.
Убедитесь, что это будет добавлено в конфигурацию службы:
<system.serviceModel>
<diagnostics performanceCounters="All" />
</system.serviceModel>
В вашей службе есть статический класс, который держит ваш PerformanceCounter. В моем примере я добавил статический экземпляр в службу, и в реальности я бы переместил его в другой класс.
public class Service1 : IService1
{
// in an ideal world thisd how instancename would look like
//[email protected] endpoint listener address
private static PerformanceCounter pc = new PerformanceCounter();
// our static constructor
static Service1()
{
// naming of the instance is garbeld due to length restrictions...
var cat = new PerformanceCounterCategory("ServiceModelOperation 4.0.0.0");
foreach (var instance in cat.GetInstanceNames())
{
Trace.WriteLine(instance); // determine the instancename and copy over :-)
}
pc.CategoryName = "ServiceModelOperation 4.0.0.0";
pc.CounterName = "Calls Per Second";
pc.InstanceName = "[email protected]:||LOCALHOST:2806|SERVICE1.SVC";
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
// do interesting stuff here
// here I have the value (in the service call but you can call this from anywhere,
// even from another thread.
// or use perfmon.exe to obtain or make a graph of the value over time...
Trace.WriteLine(pc.NextValue().ToString());
return composite;
}
}
Пользовательского Поведение
Это нестандартное поведение перехватывает призывание servicemethod и что дает возможность запускать и останавливать таймер и сохранить результат.
Добавьте следующий класс:
// custom self timing for any wcf operation
public class Timing :Attribute, IOperationBehavior, IOperationInvoker
{
IOperationInvoker innerOperationInvoker;
private string operName = "";
public Timing()
{
}
public Timing(IOperationInvoker innerOperationInvoker, string name)
{
this.innerOperationInvoker = innerOperationInvoker;
operName = name;
}
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
dispatchOperation.Invoker = new Timing(dispatchOperation.Invoker, operationDescription.Name);
}
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
object value;
var sw = new Stopwatch();
sw.Start();
value = innerOperationInvoker.Invoke(instance, inputs, out outputs);
sw.Stop();
// do what you need with the value...
Trace.WriteLine(String.Format("{0}: {1} ms", operName, sw.ElapsedMilliseconds));
return value;
}
// boring required interface stuff
public object[] AllocateInputs()
{
return innerOperationInvoker.AllocateInputs();
}
public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
{
return innerOperationInvoker.InvokeBegin(instance, inputs, callback, state);
}
public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
{
return innerOperationInvoker.InvokeEnd(instance, out outputs, result);
}
public bool IsSynchronous
{
get { return innerOperationInvoker.IsSynchronous; }
}
public void AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
// throw new NotImplementedException();
}
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
{
// throw new NotImplementedException();
}
public void Validate(OperationDescription operationDescription)
{
// throw new NotImplementedException();
}
}
Теперь декорировать в интерфейсе операции, которые вы хотите хранить свои тайминги с атрибутом Timing:
[ServiceContract]
public interface IService1
{
[OperationContract]
[Timing] // Timing for this Operation!
CompositeType GetDataUsingDataContract(CompositeType composite);
}
Вы можете объявить переменную 'класса Stopwatch' и запустите его перед вызовом и отобразите 'секундомер.Elapsed' после возврата вызова. Если вы используете потоки или задачи, немного сложно получить доступ к главному окну, чтобы отображать статистику для пользователя, но идея остается прежней. –
уверен - но не могли бы вы указать, где именно я должен назвать секундомер.Избран? – avs099
Выполняет [по умолчанию счетчик производительности WCF] (http://msdn.microsoft.com/en-us/library/vstudio/ms731055 (v = vs.100) .aspx) доставляет то, что вам нужно? – rene