我有一个提供Login方法的WCF服务.客户端需要调用此方法(因为它是唯一的IsInitiating = true).在任何情况下,此方法都应返回一个描述调用成功的字符串.如果登录失败,则应关闭连接.
问题在于收盘时间.我想发送返回值,然后立即关闭连接.
string Login (string name, string pass)
{
if (name != pass) {
OperationContext.Current.Channel.Close ();
return "fail";
}
else {
return "yay";
}
}
Run Code Online (Sandbox Code Playgroud)
在MSDN指出,呼吁Close在通道上
导致ICommunicationObject从Opened状态正常转换为Closed状态.Close方法允许在返回之前完成任何未完成的工作.例如,完成发送任何缓冲的消息).
这对我来说不起作用(或者我的理解是错误的),因为close立即执行--WCF不等待Login方法完成执行并返回字符串但是先关闭连接.
因此,我假设调用Close不会等待运行方法完成.现在,我怎么还能返回一个值,然后关闭?
在我的绝望中,我尝试了以下,但这不是一个严肃的解决方案.
new Thread (() => {
Thread.Sleep (100);
OperationContext.Current.Channel.Close ();
}).Start ();
Run Code Online (Sandbox Code Playgroud)
当文档说"优雅"时,它实际上是在谈论ICommunicationObject.Close从客户端调用时.在服务方面,如果您在客户端仍在等待响应时尝试关闭通道,那么您将度过糟糕的时光.
客户端会感到困惑,不必费心确认关闭,然后服务器将超时Close尝试,在您的情况下,工作线程正在发生,工作线程上未处理的异常不利于您的服务健康或您自己的理智.
你真正想要的不是一个优雅的连接关闭,你想要强行断开无法成功登录的客户端.为此,您必须在发送响应后注册操作完成时的事件处理程序:
public string Login(string name, string pass)
{
if (name != pass)
{
OperationContext.Current.OperationCompleted += LoginFailed;
return "fail";
}
return "yay";
}
private void LoginFailed(object sender, EventArgs e)
{
OperationContext.Current.Channel.Abort();
}
Run Code Online (Sandbox Code Playgroud)
这将做我非常确定你想做的事情 - 将"失败"发送回客户端,清理所有需要清理的东西,然后断开客户端连接,防止会话中的任何进一步活动.
顺便说一下,我不知道这与真实的服务代码有多接近,但是当你可以使用WCF的内置服务凭证系统时,在服务上使用"Login"方法有点多余.
| 归档时间: |
|
| 查看次数: |
1629 次 |
| 最近记录: |