2010-04-09 69 views
0

我有一个提供登录方法的WCF服务。客户需要调用此方法(因为它是唯一的IsInitiating = true)。这种方法应该返回一个描述调用成功的字符串。如果登录失败,连接应该关闭。WCF:如何正常关闭连接时发送数据?

问题是关闭的时间。我想发送返回值,然后立即关闭连接。

string Login (string name, string pass) 
{ 
    if (name != pass) { 
     OperationContext.Current.Channel.Close(); 
     return "fail"; 
    } 
    else { 
     return "yay"; 
    } 
} 

MSDN状态,该信道

上调用Close导致ICommunicationObject到 从打开状态 优雅地转换到关闭状态。关闭 方法允许任何未完成的工作返回前完成 。例如,对于 示例,完成发送任何缓冲的 消息)。

这对我没有帮助(或者我的理解是错误的),因为close立即执行 - WCF不会等待Login方法完成执行并返回一个字符串,但会关闭之前的连接。

因此,我认为调用Close并不等待正在运行的方法完成。现在,我还能如何返回一个值,,然后关闭?

在我的绝望中,我尝试了以下方法,但它不是一个严肃的解决方案。

new Thread (() => { 
    Thread.Sleep (100); 
    OperationContext.Current.Channel.Close(); 
}).Start(); 

回答

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”方法有点多余。

+0

好的解释!是的,那正是我想要的。 OperationCompleted事件听起来像个不错的主意,我会尝试。关于证书系统:我认为这在我的具体情况下是过分的,但我会记住并稍后看看。 – mafu 2010-04-10 12:31:38

0

为什么要关闭连接服务器端?我知道你想尽快清理任何资源。但是,为什么不通过使用WCF提供的可用限制(实例模式等)和超时选项来进行管理?

相关问题