简体   繁体   English

为WCF服务C#控制台应用程序实施超时

[英]Implementing timeout for WCF service c# console app

So I'm writing a console app that calls a WCF service (via nettcpbinding) - and the business wants to be able to specify a value to use as the timeout value. 因此,我正在编写一个控制台应用程序,该应用程序(通过nettcpbinding)调用WCF服务-该企业希望能够指定一个值用作超时值。 I originally tried operation timeout but that seemed to get ignored - so I tried a bunch of other values. 我最初尝试操作超时,但似乎被忽略了-因此我尝试了许多其他值。 One of those works (or combination of) :) 这些作品之一(或两者的结合):)

I was hoping I could still close the channel if it times out - but if I put the closing in the finally block then it sits for another minute until it times out (whereas I'm setting a timeout value in seconds). 我希望如果超时,我仍然可以关闭该通道-但是,如果我将结束放置在finally块中,则它会等待一分钟直到超时(而我正在以秒为单位设置超时值)。 I'm testing by adding a delay in the server side code - to simulate it taking awhile. 我正在通过在服务器端代码中添加延迟来进行测试-以模拟一段时间。

I can move the close to the first try block but I'm then concerned that I'll be leaving channels open. 我可以将通道移到第一个try块附近,但随后我担心通道将保持打开状态。 It then will report back the timeout error to the user a lot quicker. 然后,它将更快地向用户报告超时错误。 Or do I need to implement threading? 还是我需要实现线程化?

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);
}

Edit - I think I can use factory.Abort() to end it quicker. 编辑-我想我可以使用factory.Abort()更快地结束它。 (I'd put it where the Close is in the above code). (我把它放在上面代码中Close的位置)。

From your description, SendTimeout is exactly the value you want to tweak (see also this question on various timeouts ). 根据您的描述, SendTimeout正是您想要调整的值(另请参见有关各种超时的问题 )。 It's 1 minute by default, but if you change it to something less (eg 5 seconds) calling proxy.GetLatestPartyProfile should indeed throw a TimeoutException after 5 seconds (assuming the service call is taking more than that to respond). 默认情况下是1分钟,但是如果您将其更改为更少的时间(例如5秒),则调用proxy.GetLatestPartyProfile实际上应该在5秒后引发TimeoutException(假设服务调用花费的时间比响应更多)。

In the code you currently posted I can see at least one thing that may be causing your problems: you are setting the timeout value on the factory after you've already created the proxy. 在您当前发布的代码中,我至少可以看到一件事可能引起您的问题:创建代理后,您正在工厂设置超时值。 Reorder the relevant statements and retry. 重新排列相关语句,然后重试。 Something like this: 像这样:

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.

Note: I'm not entirely sure what your current overload voor CreateChannel uses for a binding. 注意:我不完全确定您当前的重载方式CreateChannel用于绑定的内容。 Seems plausible that it uses the binding you set earlier, but if you are still having trouble you may experiment by using the CreateChannel(Binding, EndpointAddress) overload. 似乎它使用了您之前设置的绑定似乎是合理的,但是如果仍然遇到问题,可以尝试使用CreateChannel(Binding, EndpointAddress)重载。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM