【问题标题】:Implementing timeout for WCF service c# console app为 WCF 服务 c# 控制台应用程序实现超时
【发布时间】:2026-01-31 21:30:03
【问题描述】:

所以我正在编写一个调用 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);
}

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

【问题讨论】:

  • 所以我更改了设置超时的顺序,只指定了 SendTimeout 值似乎没问题。我也在最后一次尝试捕获 - 检查通道是否打开,如果是 - 中止工厂并调用关闭。似乎不再需要永远。

标签: c# wcf nettcpbinding


【解决方案1】:

根据您的描述,SendTimeout 正是您想要调整的值(另请参阅this question on various timeouts)。默认情况下为 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.

注意:我不完全确定您当前的重载 voor CreateChannel 用于绑定。它使用您之前设置的绑定似乎是合理的,但如果您仍然遇到问题,您可以尝试使用 CreateChannel(Binding, EndpointAddress) 重载。

【讨论】:

    最近更新 更多