我有一个提供Login方法的WCF服务。客户端需要调用此方法(因为它是唯一的IsInitiating = true)。在任何情况下,此方法都应返回一个描述调用成功的字符串。如果登录失败,则应关闭连接。
问题在于结束时间。我想发送返回值,然后立即关闭连接。
string Login (string name, string pass)
{
if (name != pass) {
OperationContext.Current.Channel.Close ();
return "fail";
}
else {
return "yay";
}
}
MSDN表示在频道上调用Close
导致ICommunicationObject 优雅地从Opened过渡 状态为关闭状态。关闭 方法允许任何未完成的工作 在返回之前完成。对于 例如,完成发送任何缓冲 消息)。
这对我不起作用(或者我的理解是错误的),因为关闭立即执行 - WCF不等待Login方法完成执行并返回字符串但是先关闭连接。
因此我假设调用Close不会等待运行方法完成。现在,我怎么还能返回一个值,然后关闭?
在我的绝望中,我尝试了以下方法,但这不是一个严肃的解决方案。
new Thread (() => {
Thread.Sleep (100);
OperationContext.Current.Channel.Close ();
}).Start ();
答案 0 :(得分:6)
当文档说“优雅”时,它实际上是在谈论从客户端方面调用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();
}
这将做我非常确定你想做的事情 - 将“失败”发送回客户端,清理所有需要清理的内容,然后断开客户端连接,防止会话中的任何进一步活动。
顺便说一下,我不知道这与真实的服务代码有多接近,但是当你可以使用WCF的内置服务凭证系统时,在服务上使用“Login”方法有点多余。
答案 1 :(得分:0)
为什么要关闭连接服务器端?我知道你想尽快清理任何资源。但是,为什么不通过使用WCF提供的可用限制(实例模式等)和超时选项来管理它?