简体   繁体   English

C# WCF 客户端打开时间过长 state (DuplexClientBase<t> 。打开())</t>

[英]C# WCF Client takes too long to opened state (DuplexClientBase<T>.Open())

I'm having a little problem with a WCF client.我在使用 WCF 客户端时遇到了一点问题。 First, allow me to explain and give you details.首先,请允许我向您解释并提供详细信息。

I'm currently developing a system, and I was thinking in separate the main application because I designed it to be updated with dlls.我目前正在开发一个系统,我正在考虑单独的主应用程序,因为我将它设计为使用 dll 进行更新。 So I found MEF, and began to read a lot about it.所以我找到了 MEF,并开始大量阅读它。 But there was problem with MEF, it locks the file, no write.但是MEF有问题,它锁定了文件,没有写入。 Then I found shadow copy.然后我找到了影子副本。 So now I placed the client in another AppDomain in the main Application.所以现在我将客户端放在主应用程序的另一个 AppDomain 中。 I've read that communication cross domains is possible through NET Remoting, so I made research and done it with WCF.我已经读过可以通过 NET Remoting 进行跨域通信,因此我进行了研究并使用 WCF 完成了它。

The main Application is the host, it loads the assembly in a new domain and starts the client.主应用程序是主机,它将程序集加载到新域中并启动客户端。 As the client is a DLL, there is no AppConfig file to load bindings, endpoints.由于客户端是 DLL,因此没有 AppConfig 文件来加载绑定、端点。 I've created a class that helps me with that, so the config is added programatically.我创建了一个 class 来帮助我,所以配置是以编程方式添加的。

Finally, it works!最后,它起作用了!

But there is a little thing I don't think is ok.但是有一点我觉得不太好。 In the client, when the instruction DuplexClientBase.Open() is executed, it takes 20 seconds to open.在客户端,当指令 DuplexClientBase.Open() 被执行时,需要 20 秒才能打开。 I think is not OK 'cause when I move the client to a EXE (remember is a DLL and the config is added programatically) it doesn't take all that time.我认为这不好,因为当我将客户端移动到 EXE 时(记住是 DLL 并且配置是通过编程方式添加的)它并不需要所有时间。

Maybe is something wrong in the config, but I can't find it.也许是配置中有问题,但我找不到。 So here are the souce code files.所以这里是源代码文件。 First, this is the App.config file, when the client is in a console application:首先,这是 App.config 文件,当客户端在控制台应用程序中时:

<configuration>
<system.serviceModel>
    <bindings>
        <netTcpBinding>
            <binding name="TcpBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
                receiveTimeout="00:10:00" sendTimeout="00:01:00" transactionFlow="false"
                transferMode="Buffered" transactionProtocol="OleTransactions"
                hostNameComparisonMode="StrongWildcard" listenBacklog="10"
                maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10"
                maxReceivedMessageSize="65536">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <reliableSession ordered="true" inactivityTimeout="00:10:00"
                    enabled="false" />
                <security mode="Transport">
                    <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
                    <message clientCredentialType="Windows" />
                </security>
            </binding>
        </netTcpBinding>
        <wsDualHttpBinding>
            <binding name="HttpBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
                receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false"
                transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <reliableSession ordered="true" inactivityTimeout="00:10:00" />
                <security mode="Message">
                    <message clientCredentialType="Windows" negotiateServiceCredential="true"
                        algorithmSuite="Default" />
                </security>
            </binding>
        </wsDualHttpBinding>
    </bindings>
    <client>
        <endpoint address="net.tcp://localhost:8080/ProtoServicio/EPServicioTcp"
            binding="netTcpBinding" bindingConfiguration="TcpBinding"
            contract="TestServicio.IServicio" name="TcpBinding">
            <identity>
                <userPrincipalName value="OlinzerLaptopV\Olinzer" />
            </identity>
        </endpoint>
        <endpoint address="http://localhost:8081/ProtoServicio/EPServicioHttp"
            binding="wsDualHttpBinding" bindingConfiguration="HttpBinding"
            contract="TestServicio.IServicio" name="HttpBinding">
            <identity>
                <userPrincipalName value="OlinzerLaptopV\Olinzer" />
            </identity>
        </endpoint>
    </client>
</system.serviceModel>

And now, this is the code that creates the binding and endpoint:现在,这是创建绑定和端点的代码:

        internal static Binding GetBinding()
    {
        WSDualHttpBinding binding = new WSDualHttpBinding();
        TimeSpan span = new TimeSpan( 0, 1, 0 );

        binding.Name = "HttpBinding";
        binding.CloseTimeout = span;
        binding.OpenTimeout = span;
        binding.ReceiveTimeout = span;
        binding.SendTimeout = span;
        binding.BypassProxyOnLocal = false;
        binding.TransactionFlow = false;
        binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
        binding.MaxBufferPoolSize = 524288;
        binding.MaxReceivedMessageSize = 65536;
        binding.MessageEncoding = WSMessageEncoding.Text;
        binding.TextEncoding = Encoding.UTF8;
        binding.UseDefaultWebProxy = true;

        binding.ReaderQuotas = new XmlDictionaryReaderQuotas();
        binding.ReaderQuotas.MaxDepth = 32;
        binding.ReaderQuotas.MaxStringContentLength = 8192;
        binding.ReaderQuotas.MaxArrayLength = 16384;
        binding.ReaderQuotas.MaxBytesPerRead = 4096;
        binding.ReaderQuotas.MaxNameTableCharCount = 16384;

        binding.ReliableSession = new ReliableSession();
        binding.ReliableSession.Ordered = true;
        binding.ReliableSession.InactivityTimeout = span;

        binding.Security.Mode = WSDualHttpSecurityMode.Message;

        binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
        binding.Security.Message.NegotiateServiceCredential = true;
        binding.Security.Message.AlgorithmSuite = SecurityAlgorithmSuite.Default;

        return binding;
    }

The file created by the code only contains the Http Endpoint.代码创建的文件仅包含 Http Endpoint。 Maybe adding the tcp endpoint could make the diference, but, I have no idea how to make it.也许添加 tcp 端点可能会有所不同,但是,我不知道如何做到这一点。 The function above is called by the constructor of the ClientClientBase class.上面的function是由ClientClientBase class的构造函数调用的。

ServiceModel.DuplexClientBase<Servicio> MyClient = new ...<Servicio>(new InstanceContext(this), GetBinding(), GetEndpoint());

Feel free to notify me if you need anything else.如果您需要其他任何东西,请随时通知我。

You are doing cross AppDomain communication within single process and you are using WsHttpBinding ?您正在单个进程中进行跨 AppDomain 通信并且正在使用WsHttpBinding Do you understand how big overhead this has?你知道这有多大的开销吗? It also highly increases complexity of your application deployment.它还极大地增加了应用程序部署的复杂性。 It is probably not source of your main problem but I would start with:它可能不是您的主要问题的根源,但我将从:

  • Replacing WsDualHttpBinding with NetNamedPipeBindingNetNamedPipeBinding替换WsDualHttpBinding

To diagnosing your issue start with WCF tracing and check which operation on both client and server takes a long time - there can be problem with some security resolving because your setting uses message security.要诊断您的问题,请从WCF 跟踪开始,并检查客户端和服务器上的哪些操作需要很长时间 - 由于您的设置使用消息安全性,因此某些安全性解决可能会出现问题。

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

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