在某些博客文章里,直接将 IsOneWay 称为 "异步方法"。虽然多数时候不会对开发带来什么问题,但深究起来,这两者是不同的。接下来,我们做个试验。将同一个服务契约分别用 IsOneWay 和异步进行实现,客户端使用多线程模拟并发调用,并使用 ServiceThrottlingBehavior (也可以使用 InstanceContextMode.Single) 进行并发控制。注意对比输出结果,我们就会发现其不同之处。
IsOneWay版本
[ServiceContract]
public interface IService
{
[OperationContract(IsOneWay=true)]
void Test();
}
public class MyService : IService
{
public void Test()
{
Console.WriteLine("Service BeginAdd:{0}", DateTime.Now);
Thread.Sleep(5000);
Console.WriteLine("Service EndAdd:{0}", DateTime.Now);
}
}
public class WcfTest
{
public static void Test()
{
AppDomain.CreateDomain("Server").DoCallBack(delegate
{
ServiceHost host = new ServiceHost(typeof(MyService));
host.AddServiceEndpoint(typeof(IService), new WSHttpBinding(), "http://localhost:8080/myservice");
ServiceThrottlingBehavior throttling = new ServiceThrottlingBehavior();
throttling.MaxConcurrentInstances = 1;
host.Description.Behaviors.Add(throttling);
host.Open();
});
for (int i = 0; i < 3; i++)
{
new Thread(delegate()
{
IService channel = ChannelFactory<IService>.CreateChannel(new WSHttpBinding(),
new EndpointAddress("http://localhost:8080/myservice"));
using (channel as IDisposable)
{
Console.WriteLine("Client {0} BeginAdd:{1}",
Thread.CurrentThread.ManagedThreadId, DateTime.Now);
channel.Test();
Console.WriteLine("Client {0} BeginAdd End:{1}",
Thread.CurrentThread.ManagedThreadId, DateTime.Now);
}
}).Start();
}
}
}
输出:
Client 15 BeginAdd:2007-4-19 10:51:39
Client 14 BeginAdd:2007-4-19 10:51:39
Client 16 BeginAdd:2007-4-19 10:51:39
Client 16 BeginAdd End:2007-4-19 10:51:40
Service BeginAdd:2007-4-19 10:51:40
Service EndAdd:2007-4-19 10:51:45
Client 14 BeginAdd End:2007-4-19 10:51:46
Service BeginAdd:2007-4-19 10:51:46
Service EndAdd:2007-4-19 10:51:51
Service BeginAdd:2007-4-19 10:51:51
Client 15 BeginAdd End:2007-4-19 10:51:51
Service EndAdd:2007-4-19 10:51:56
异步版本
[ServiceContract]
public interface IService
{
[OperationContract]
void Test();
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginTest(AsyncCallback callBack, object state);
void EndTest(IAsyncResult ar);
}
public class MyService : IService
{
public void Test()
{
Console.WriteLine("Service BeginAdd:{0}", DateTime.Now);
Thread.Sleep(5000);
Console.WriteLine("Service EndAdd:{0}", DateTime.Now);
}
public IAsyncResult BeginTest(AsyncCallback callBack, object state)
{
throw new Exception("The method or operation is not implemented.");
}
public void EndTest(IAsyncResult ar)
{
throw new Exception("The method or operation is not implemented.");
}
}
public class WcfTest
{
public static void Test()
{
AppDomain.CreateDomain("Server").DoCallBack(delegate
{
ServiceHost host = new ServiceHost(typeof(MyService));
host.AddServiceEndpoint(typeof(IService), new WSHttpBinding(), "http://localhost:8080/myservice");
ServiceThrottlingBehavior throttling = new ServiceThrottlingBehavior();
throttling.MaxConcurrentInstances = 1;
host.Description.Behaviors.Add(throttling);
host.Open();
});
for (int i = 0; i < 3; i++)
{
new Thread(delegate()
{
IService channel = ChannelFactory<IService>.CreateChannel(new WSHttpBinding(),
new EndpointAddress("http://localhost:8080/myservice"));
using (channel as IDisposable)
{
Console.WriteLine("Client {0} BeginAdd:{1}",
Thread.CurrentThread.ManagedThreadId, DateTime.Now);
IAsyncResult ar = channel.BeginTest(null, null);
Console.WriteLine("Client {0} BeginAdd End:{1}",
Thread.CurrentThread.ManagedThreadId, DateTime.Now);
channel.EndTest(ar);
}
}).Start();
}
}
}
输出:
Client 14 BeginAdd:2007-4-19 10:53:56
Client 16 BeginAdd:2007-4-19 10:53:56
Client 15 BeginAdd:2007-4-19 10:53:56
Client 16 BeginAdd End:2007-4-19 10:53:56
Client 14 BeginAdd End:2007-4-19 10:53:56
Client 15 BeginAdd End:2007-4-19 10:53:56
Service BeginAdd:2007-4-19 10:53:59
Service EndAdd:2007-4-19 10:54:04
Service BeginAdd:2007-4-19 10:54:04
Service EndAdd:2007-4-19 10:54:09
Service BeginAdd:2007-4-19 10:54:09
Service EndAdd:2007-4-19 10:54:14
通过对比,我们发现异步方法 BeginXXX 调用并不受并发控制影响,调用后直接返回控制权;而 IsOneWay 则不同,它被阻塞直到服务方法获得执行才会返回(当然,没有等待服务方法执行完成)。这点区别在处理并发性能上,可能带来不同的效果,了解 IsOneWay 和异步的差别能让我们避免一些意外的问题。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zengjibing/archive/2009/01/17/3813601.aspx