客户端调用方法我的网络WCF服务的“富()” - 和接收大字节数组作为响应:如何以编程方式跟踪响应持续时间?
public byte[] Foo()
{
return new byte[10000000];
}
显然,当客户端读取所有数据,HTTP连接被关闭 - 如果我知道什么时候发生这种情况,我可以追踪“传播”的总持续时间。我知道跟踪等 - 但我需要以编程方式具有此数据,所以我可以将其显示给用户。我如何跟踪这个?
客户端调用方法我的网络WCF服务的“富()” - 和接收大字节数组作为响应:如何以编程方式跟踪响应持续时间?
public byte[] Foo()
{
return new byte[10000000];
}
显然,当客户端读取所有数据,HTTP连接被关闭 - 如果我知道什么时候发生这种情况,我可以追踪“传播”的总持续时间。我知道跟踪等 - 但我需要以编程方式具有此数据,所以我可以将其显示给用户。我如何跟踪这个?
您可以使用秒表类,找出时间是指这个MSDN链接:
http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.elapsed.aspx
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
// your wcf functionalities
stopWatch.Stop();
long duration = stopWatch.ElapsedMilliseconds;
'stopWatch.Elapsed'是一个'TimeSpan'属性,比普通的毫秒更容易操作。 –
我的Foo()方法是从CLIENT调用的,我不会从我的代码中调用它。 – avs099
@ avs099是的,Foo()会被客户端调用,但是使用秒表,你可以计算你的wcf服务执行你的功能的总持续时间,然后你可以发送该持续时间给客户端或显示它,但是你想要的,我的意思是在您的SERVICE代码中。 –
我有两个解决方案,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();
}
}
现在装点在你的界面,您希望将自己的时序存储与时序属性的操作:
[ServiceContract]
public interface IService1
{
[OperationContract]
[Timing] // Timing for this Operation!
CompositeType GetDataUsingDataContract(CompositeType composite);
}
你可以声明'Stopwatch'类变量并在通话之前启动并在通话结束后显示“stopwatch.Elapsed”。如果您使用线程或任务,访问主窗口以向用户显示统计信息有点困难,但这个想法保持不变。 –
肯定 - 但你能否指定我应该打电话给stopwatch.Elapsed? – avs099
执行[默认的WCF性能计数器](http://msdn.microsoft.com/en-us/library/vstudio/ms731055(v = vs.100).aspx)是否提供您所需要的? – rene