为WCF服务c#控制台应用程序实现超时

为WCF服务c#控制台应用程序实现超时,c#,wcf,nettcpbinding,C#,Wcf,Nettcpbinding,因此,我正在编写一个控制台应用程序来调用WCF服务(通过nettcpbinding)——业务部门希望能够指定一个值作为超时值。我最初尝试操作超时,但似乎被忽略了,所以我尝试了一系列其他值。这些作品之一(或组合):) 我希望如果通道超时,我仍然可以关闭它-但是如果我将关闭放在finally块中,它会再等待一分钟直到超时(而我正在设置以秒为单位的超时值)。我通过在服务器端代码中添加一个延迟来进行测试,以模拟一段时间 我可以移动到靠近第一个试块的地方,但我担心我会让频道保持开放。然后它会更快地向用户报

因此,我正在编写一个控制台应用程序来调用WCF服务(通过nettcpbinding)——业务部门希望能够指定一个值作为超时值。我最初尝试操作超时,但似乎被忽略了,所以我尝试了一系列其他值。这些作品之一(或组合):)

我希望如果通道超时,我仍然可以关闭它-但是如果我将关闭放在finally块中,它会再等待一分钟直到超时(而我正在设置以秒为单位的超时值)。我通过在服务器端代码中添加一个延迟来进行测试,以模拟一段时间

我可以移动到靠近第一个试块的地方,但我担心我会让频道保持开放。然后它会更快地向用户报告超时错误。还是我需要实现线程

public static String ExecuteSearch(List<KeyValuePair<string, string>> paramItems)
{
    var context = GetAdminContext();
    var parsedParameters = ParseParameters((paramItems));

    //TODO: Figure out how to implement timeout - & workout if port number will be passed in?? 
    IPartyProfile partyProfile = null;

    long start = System.Environment.TickCount;

    using (ChannelFactory<IPartyController> factory = new ChannelFactory<IPartyController>("IPartyControllerEndpoint"))
    {
        EndpointAddress address = new EndpointAddress(String.Format("net.tcp://{0}/ServiceInterface/PartyController.svc", parsedParameters.HostName));
        IPartyController proxy = factory.CreateChannel(address);

        if (proxy != null)
        {
            var timeoutTimeSpan = new TimeSpan(0, 0, parsedParameters.TimeOut);
            ((IContextChannel)proxy).OperationTimeout = timeoutTimeSpan;
            factory.Endpoint.Binding.SendTimeout = timeoutTimeSpan;
            factory.Endpoint.Binding.ReceiveTimeout = timeoutTimeSpan;
            factory.Endpoint.Binding.OpenTimeout = timeoutTimeSpan;
            factory.Endpoint.Binding.CloseTimeout = timeoutTimeSpan;

            try
            {
                // TODO: potentially call something more complex
                partyProfile = proxy.GetLatestPartyProfile(context, parsedParameters.PartyId);

            }
            catch (EndpointNotFoundException ex)
            {
                throw new Exception(STATUS_UNKNOWN + ": Endpoint specified not responding", ex);
            }
            catch (TimeoutException ex)
            {
                throw new Exception(STATUS_UNKNOWN + ": Timeout exceeded", ex);
            }
            finally
            {
                try
                {
                    ((IClientChannel)proxy).Close();
                }
                catch (Exception)
                {
                }

            }
        }
    }

    long stop = System.Environment.TickCount;
    long elapsed = (stop - start) / 1000; // in seconds

    return SetResultMessage(elapsed, partyProfile, parsedParameters);
}
publicstaticstringexecutesearch(列出参数项)
{
var context=GetAdminContext();
var parsedParameters=ParseParameters((paramItems));
//TODO:如果要传入端口号,请确定如何实施超时和训练??
IPartyProfile partyProfile=null;
长启动=System.Environment.TickCount;
使用(ChannelFactory工厂=新的ChannelFactory(“IPartyControllerEndpoint”))
{
EndpointAddress address=新的EndpointAddress(String.Format(“net.tcp://{0}/ServiceInterface/PartyController.svc”,parsedParameters.HostName));
IPartyController代理=factory.CreateChannel(地址);
如果(代理!=null)
{
var timeoutTimeSpan=new TimeSpan(0,0,parsedParameters.TimeOut);
((IContextChannel)代理)。操作超时=超时时间跨度;
factory.Endpoint.Binding.SendTimeout=timeoutTimeSpan;
factory.Endpoint.Binding.ReceiveTimeout=timeoutTimeSpan;
factory.Endpoint.Binding.OpenTimeout=timeoutTimeSpan;
factory.Endpoint.Binding.CloseTimeout=timeoutTimeSpan;
尝试
{
//待办事项:可能称之为更复杂的事情
partyProfile=proxy.GetLatestPartyProfile(上下文,parsedParameters.PartyId);
}
捕获(EndpointNotFoundException ex)
{
抛出新异常(状态_未知+“:指定的端点未响应”,ex);
}
捕获(TimeoutException例外)
{
抛出新异常(状态_未知+“:超时超过”,ex);
}
最后
{
尝试
{
((IClientChannel)代理).Close();
}
捕获(例外)
{
}
}
}
}
长时间停止=System.Environment.TickCount;
长时间运行=(停止-启动)/1000;//秒
返回SetResultMessage(已用、partyProfile、parsedParameters);
}

编辑-我想我可以使用factory.Abort()更快地结束它。(我把它放在上面代码中的结束位置)。

根据您的描述,
SendTimeout
正是您想要调整的值(另请参见)。默认情况下为1分钟,但如果将其更改为更短的时间(例如5秒),则调用
proxy.GetLatestPartyProfile
确实应该在5秒后抛出TimeoutException(假设服务调用的响应时间超过该时间)

在您当前发布的代码中,我至少可以看到一件可能会导致您出现问题的事情:在您已经创建代理之后,您正在工厂上设置超时值。对相关语句重新排序,然后重试。大概是这样的:

using (ChannelFactory<IPartyController> factory = new ChannelFactory<IPartyController>("IPartyControllerEndpoint"))
{
    var timeoutTimeSpan = new TimeSpan(0, 0, parsedParameters.TimeOut);
    factory.Endpoint.Binding.SendTimeout = timeoutTimeSpan;

    EndpointAddress address = new EndpointAddress(String.Format("net.tcp://{0}/ServiceInterface/PartyController.svc", parsedParameters.HostName));
    IPartyController proxy = factory.CreateChannel(address);

    if (proxy != null)
    {
        try
        {
            // TODO: potentially call something more complex
            partyProfile = proxy.GetLatestPartyProfile(context, parsedParameters.PartyId);
        }
        // etc.
使用(ChannelFactory工厂=新的ChannelFactory(“IPartyControllerEndpoint”))
{
var timeoutTimeSpan=new TimeSpan(0,0,parsedParameters.TimeOut);
factory.Endpoint.Binding.SendTimeout=timeoutTimeSpan;
EndpointAddress address=新的EndpointAddress(String.Format(“net.tcp://{0}/ServiceInterface/PartyController.svc”,parsedParameters.HostName));
IPartyController代理=factory.CreateChannel(地址);
如果(代理!=null)
{
尝试
{
//待办事项:可能称之为更复杂的事情
partyProfile=proxy.GetLatestPartyProfile(上下文,parsedParameters.PartyId);
}
//等等。

注意:我不完全确定您当前的重载voor
CreateChannel
用于绑定的内容。它使用您之前设置的绑定似乎是合理的,但是如果您仍然有问题,您可以使用重载进行实验。

因此,我更改了设置超时的顺序,似乎只使用SendTimeo就可以了ut值被指定。我也在我的try-catch的最后一步-检查通道是否打开,如果打开-中止工厂并调用close。这似乎不再需要很长时间了。