WCF generating high computer usage and network storm

About Author:
MVPLeo Lorenzo Luis is a Microsoft MVP, he has also been a Microsoft Student Partner from 2009 to 2011, and became a Worldwide Imagine Cup Finalist to represent the Philippines for 2011 that was held in New York, United States. He is passionate in developing applications in the .NET Framework and has been helping the community to share his expertise and knowledge about the technology. More about Leo on his website http://www.luisleo.net
Symptoms
When using Windows Communication Foundation (WCF) support for WS-Discovery over UDP, you may see one or more of the following problems:

1.) Hits the following exception in an infinite loop

Type: ArgumentException
Message: The 'result' argument must be of type Message
Stack trace:
at System.ServiceModel.Dispatcher.MessageOperationFormatter.SerializeReply(MessageVersion messageVersion, Object[] parameters, Object result)

2.) Network storms

3.) Generates a high CPU usage even after FindCompleted is called

4.) Keeps sending SOAP Fault exception being sent over with .NET 4.5

5.) High multicast traffic
Cause
1. Microsoft internal bug in the WCF Framework 4.0

2. WCF keeps sending fault exceptions

3. The WCF service hosts multiple UDP Multicast Services where more than one service shares a given multicast address and port
Resolution
To resolve this issue, apply one of the updates that are described in the following Knowledge Base (KB) articles:
  • 2805226 An update is available for the .NET Framework 4.5 in Windows 7 SP1, Windows Server 2008 R2 SP1, Windows Server 2008 SP2, and Windows Vista SP2: May 2013
  • 2805227 An update is available for the .NET Framework 4.5 in Windows 8, Windows RT, and Windows Server 2012: May 2013
Note For more information about this issue, see "Issue 2" in the "WCF" section.
Workarounds
There are a lot of different ways to solve this problem for now and Microsoft is aware of the bug and will release a hot fix soon.

  1. First Workaround

    The first work around is first discovered by Michael A. Shields (Pyramid Systems, Inc.) Developer. It is just basically uses reflection and this was a work around that removes the "System.ServiceModel.Discovery.UdpContractFilterBehavior" in the Behaviors of the endpoint.
    AnnouncementService announcementService = new AnnouncementService();var endpoint = new UdpAnnouncementEndpoint();var behavior = endpoint.Behaviors.FirstOrDefault(e => e.GetType().FullName == "System.ServiceModel.Discovery.UdpContractFilterBehavior");if (behavior != null) endpoint.Behaviors.Remove(behavior);ServiceHost host = new ServiceHost(announcementService);host.AddServiceEndpoint(endpoint);host.Open();
  2. Second Workaround

    The second work around is made by Wayne Xiong (Microsoft). Instead of using reflection we create a custom behavior and use that class when using a UdpAnnouncementEndPoint and add it to it's behaviors. Which is where the first work around came from.

    CustomBehaviorClass.cs
    class WorkaroundBehavior : IEndpointBehavior{ public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) {         }         public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) {  if (clientRuntime == null)  {    throw new ArgumentNullException("clientRuntime");  }  clientRuntime.CallbackDispatchRuntime.UnhandledDispatchOperation.Invoker = new UnhandledActionOperationInvoker(); } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { } public void Validate(ServiceEndpoint endpoint) { } class UnhandledActionOperationInvoker : IOperationInvoker {  public bool IsSynchronous  {   get   {    return true;   }  } public object[] AllocateInputs() {  return new object[1]; } public object Invoke(object instance, object[] inputs, out object[] outputs) {  outputs = new object[0];  return Message.CreateMessage(MessageVersion.None, string.Empty); } public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state) {  throw new NotImplementedException(); } public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result) {  throw new NotImplementedException(); } }}

    MainWindow.cs
    UdpDiscoveryEndpoint clientEndpoint = new UdpDiscoveryEndpoint();clientEndpoint.Behaviors.Add(new WorkaroundBehavior());var discoveryClient = new DiscoveryClient(clientEndpoint);
    Note from Wayne Xiong :
    If you do not have access to the server-side code, you can add the following on the client-side instead. Add this behavior to your client-side UdpDiscoveryEndpoint. This workaround must be applied to all Discovery clients whether they are compiled in .NET 4.5 or in .NET 4.0
  3. Third Workaround

    Use a unique multicast address and/or port for each service listening on the SOAP.UDP protocol.
  4. Fourth Workaround

    The last work around is from Jon Cole (Microsoft). Programmatically force the transport to use duplex channel, instead of the IReplyChannel that was introduced in 4.5. Following is a C# code sample to accomplish this on the service side (on the server). Using the following class, we can have a custom implementation of CanBuildChannelListener that returns false for IReplyChannel:

    CustomClass.cs
    class DisableIReplyChannelShapeBindingElement : BindingElement{    public override BindingElement Clone()    {        return this;    }    public override T GetProperty<T>(BindingContext context)    {        return null;    }    public override bool CanBuildChannelListener<TChannel>(BindingContext context)    {        if (typeof(TChannel) == typeof(IReplyChannel))        {            return false;        }        return context.CanBuildInnerChannelListener<TChannel>();    }}
    By inserting this into the binding, your application can hide the fact that the UDP transport supports the IReplyChannel shape from the Announcement endpoint, which will avoid the problem. Following is a helper method that will be used later:

    HelperClass.cs

    public static void DisableIReplyChannelShape(ServiceEndpoint endpoint){    CustomBinding customBinding = new CustomBinding(endpoint.Binding);    //only do this if using the UdpTransport.    if (customBinding.Elements.Find<UdpTransportBindingElement>() != null)    {                        customBinding.Elements.Insert(customBinding.Elements.Count - 1, new DisableIReplyChannelShapeBindingElement());        endpoint.Binding = customBinding;    }            }
    You can stop your server-side code from sending the fault messages that are causing problems by doing the following to your AnnouncementEndpoint:

    UdpAnnouncementEndpoint announcementEndpoint = new UdpAnnouncementEndpoint();DisableIReplyChannelShape(announcementEndpoint);

Community Solutions Content Disclaimer

MICROSOFT CORPORATION AND/OR ITS RESPECTIVE SUPPLIERS MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY, RELIABILITY, OR ACCURACY OF THE INFORMATION AND RELATED GRAPHICS CONTAINED HEREIN. ALL SUCH INFORMATION AND RELATED GRAPHICS ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT AND/OR ITS RESPECTIVE SUPPLIERS HEREBY DISCLAIM ALL WARRANTIES AND CONDITIONS WITH REGARD TO THIS INFORMATION AND RELATED GRAPHICS, INCLUDING ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, WORKMANLIKE EFFORT, TITLE AND NON-INFRINGEMENT. YOU SPECIFICALLY AGREE THAT IN NO EVENT SHALL MICROSOFT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY DIRECT, INDIRECT, PUNITIVE, INCIDENTAL, SPECIAL, CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF USE, DATA OR PROFITS, ARISING OUT OF OR IN ANY WAY CONNECTED WITH THE USE OF OR INABILITY TO USE THE INFORMATION AND RELATED GRAPHICS CONTAINED HEREIN, WHETHER BASED ON CONTRACT, TORT, NEGLIGENCE, STRICT LIABILITY OR OTHERWISE, EVEN IF MICROSOFT OR ANY OF ITS SUPPLIERS HAS BEEN ADVISED OF THE POSSIBILITY OF DAMAGES.
Vlastnosti

ID článku: 2786802 - Poslední kontrola: 09/25/2013 11:09:00 - Revize: 7.1

Windows Communication Foundation 4, Windows Communication Foundation 4.5

  • kbstepbystep kbmvp kbcommunity KB2786802
Váš názor