我有一个客户端应用程序,一旦进入通知服务进度.对服务的方法调用标记为IsOneWay = true,因为通知不需要任何返回值,我不想延迟.
客户端可以向服务通知错误,然后终止.
问题是:单向方法调用在发送消息后是否返回到调用者代码?或者它将消息排队,稍后由另一个线程发送?
这两个进程(客户端和服务)在同一台机器上,我注意到有时(当机器超载时)服务没有收到错误通知.我怀疑我提到的第二个选项发生了,但我不确定.
如果我是对的,我如何确保通知发送并保持方法?
好问题.在客户端应用程序调用方法之前,它会打开通道.该通道用于所有数据通信.有两种发送方式:1)可靠会话 - 当您的数据包被可靠地删除并且重新发送破解的数据包时,2)排序 - 当服务上的请求按照从客户端传输的顺序计算时(不是它们如何传送) .如果您有可靠的有序会话,并且服务主机在关闭应用程序后遇到数据问题,主机将尝试询问客户端重新发送的数据,并且在没有响应后拒绝您请求的所有内容.在其他情况下(不可靠)打开通道后你可以发送数据并销毁通信,单向方法会计算你的请求,如果没有异常.
为了测试一些服务问题的可能性(不完全是你的客户端paroblem,但是有用)我创建了一个解决方案:
1)具有一个文件"IService1.cs"的库项目"WcfContracts":
[ServiceContract] public interface IService1 { [OperationContract] void ThrowException(); [OperationContract(IsOneWay=true)] void ThrowExceptionUseIsOneWay(); }
2)控制台项目"WcfConsoleHoster",它引用了两个"WcfContracts",并由三个文件组成:
a)Service1.cs,这是服务实现
public class Service1 : WcfContracts.IService1 { public void ThrowException() { throw new Exception("Basic exception"); } public void ThrowExceptionUseIsOneWay() { throw new Exception("Basic exception using IsOneWay=true"); } }
b)Program.cs,它具有默认入口点并且只是启动服务
static void Main(string[] args) { ServiceHost host = new ServiceHost(typeof(Service1)); host.Open(); Console.WriteLine("host 1 opened"); Console.ReadKey(); }
c)服务"App.config"
3)控制台项目"WcfConsoleClient",它只是调用服务
a)在"Program.cs"中
Console.WriteLine("Wcf client. Press any key to start"); Console.ReadKey(); ChannelFactoryfactory = new ChannelFactory ("Service1_Endpoint"); IService1 channel = factory.CreateChannel(); //Call service method channel.ThrowException(); Console.WriteLine("Operation executed"); Console.ReadKey();
b)客户端"App.config"
1.投掷例外.首先,我们调用双向方法,在服务器主机中抛出异常.然后,此异常返回到客户端,并且通道在客户端引发它,应用程序被销毁.当然你可以使用try()catch {}块来处理这个问题.
让我们通过调用单向方法看起来一样channel.ThrowExceptionUseIsOneWay();
.在服务主机中引发异常,但客户端没有异常,我们得到"操作已执行".重要的是要意识到该频道将不可用于下次使用.
因此IsOneWay=true
按预期工作 - 它只以一种方式发送消息.您不能从方法返回任何对象(预期为void),并且您不能使用FaultContract,或者在服务启动后获取InvalidOperationException.
2. Thread.Sleep().接下来的测试是关于大规模的操作Thread.Sleep()
.
IService1
延伸到
[OperationContract] int ThreadSleep(); [OperationContract(IsOneWay=true)]
并且Service1.cs中的实现正在等待5秒钟
public int ThreadSleep() { System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5)); return 1; } public void ThreadSleepUseIsOneWay() { System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5)); }
现在对客户端进行一点修改以计算已用完的呼叫时间
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Start(); //call methode channel.ThreadSleep(); stopwatch.Stop(); Console.WriteLine(string.Format("Operation executed in {0} seconds", stopwatch.Elapsed.Seconds)); Console.ReadKey();
调用双向方法 ThreadSleep()
的结果是"在7秒内执行操作"(线程休眠为5秒,通道初始化为2秒).
One way method
与调用channel.ThreadSleepUseIsOneWay()
结果"0秒"!没有等待服务响应!
最好使用NetNamedPipeBinding,它在同一台机器上可靠,快速地连接.