Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Simple call to Web Service results in OutOfMemoryException

Posted on 2014-01-14
8
Medium Priority
?
1,795 Views
Last Modified: 2014-01-16
Hi Experts,

I have a very simple Windows Mobile 6.0 application that polls a WCF web service (basicHTTPBinding, using XML messaging, hoasted in a Windows Service) every 500ms (counted after the conclusion of each web service call).  The function returns an array of enums (NEVER more than two enums returned at a time).  The application runs just fine for a couple of minutes and then all of the sudden I get the dreaded OutOfMemoryException as I try to execute the web service call.  It almost seems like the framework is grabbing memory to handle the sending and receiving of the web service messages and then it never frees it up again.

The stack trace for the error looks like this:

   at System.Reflection.Assembly.GetManifestResourceStream(String name)
   at System.Reflection.Assembly.GetManifestResourceStream(Type type, String name)
   at System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo culture, Boolean createIfNotExists, Boolean tryParents)
   at System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo culture, Boolean createIfNotExists, Boolean tryParents)
   at System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo culture, Boolean createIfNotExists, Boolean tryParents)
   at System.Resources.ResourceManager.GetString(String name, CultureInfo culture)
   at System.Resources.ResourceManager.GetString(String name)
   at System.SRSupport.GetString(String key, Object[] args)
   at System.SRSupport.GetString(Int32 resource, Object[] args)
   at System.Xml.Res.GetString(Int32 resource, Object[] args)
   at System.Xml.Serialization.XmlSerializationReflector.AddType(Type type, Boolean encoded, String defaultNS, Boolean genericNullableArg)
   at System.Xml.Serialization.XmlSerializationReflector.FindType(Type type, Boolean encoded, Boolean genericNullableArg, String defaultNamespace)
   at System.Xml.Serialization.XmlSerializationReflector.FindType(Type type, Boolean encoded, String defaultNamespace)
   at System.Xml.Serialization.XmlSerializationReflector.ResolveLiteralTypeUsingDeclaredType(Type memberType, String defaultNS, LogicalType& type, LogicalType& elementType, Boolean& isArray)
   at System.Xml.Serialization.XmlSerializationReflector.ResolveLiteralType(String attrDataType, Type attrType, Type memberType, String defaultNS, Boolean& isArray, LogicalType& type, LogicalType& elementType)
   at System.Xml.Serialization.XmlSerializationReflector.ReflectXmlElementAttributes(Type memberType, LogicalMemberValue memberValue, String memberName, LiteralAttributes attrProv, AccessorCollection memberAccessors, String defaultName, String defaultNS, Type& serializingType, Boolean& shouldBeOrdered)
   at System.Xml.Serialization.XmlSerializationReflector.ReflectLiteralMemberValue(Type memberType, String memberName, LiteralAttributes attrProv, String defaultName, String defaultNS, IEntityFinder memberFinder, Boolean canRead, Boolean canWrite, Boolean& shouldBeOrdered)
   at System.Xml.Serialization.XmlSerializationReflector.ReflectMemberValue(Type memberType, ICustomAttributeProvider attrProv, String defaultName, String defaultNS, IEntityFinder memberFinder, Fetcher fetcher, Fixup fixup, MemberValueCollection members, Boolean encoded, Boolean canRead, Boolean canWrite, Byte& specialType, Boolean& shouldBeOrdered)
   at System.Xml.Serialization.XmlSerializationReflector.addComplexTypeMemberHelper(Type type, MemberInfo member, Boolean encoded, String defaultNS, Boolean& shouldBeOrdered, IEntityFinder choiceFinder, MemberValueCollection members, String typeNS, String defaultMemberNS, Int32& sequenceId)
   at System.Xml.Serialization.XmlSerializationReflector.AddComplexType(Type type, TypeAttributes attrs, String typeName, String typeNS, Boolean typeIsNullable, Boolean encoded, String defaultNS, Boolean genericNullableArg)
   at System.Xml.Serialization.XmlSerializationReflector.AddType(Type type, Boolean encoded, String defaultNS, Boolean genericNullableArg)
   at System.Xml.Serialization.XmlSerializationReflector.FindType(Type type, Boolean encoded, String defaultNamespace, Boolean searchIntrinsics)
   at System.Xml.Serialization.XmlSerializer.findTypeByType(Type type, String defaultNamespace)
   at System.Xml.Serialization.XmlSerializer..ctor(Type type, XmlAttributeOverrides overrides, Type[] extraTypes, XmlRootAttribute root, String defaultNamespace)
   at Microsoft.Tools.ServiceModel.CFClientBase`1.CFContractSerializer.createSerializer(XmlQualifiedName wrapper)
   at Microsoft.Tools.ServiceModel.CFClientBase`1.CFContractSerializer..ctor(CFContractSerializerInfo info)
   at Microsoft.Tools.ServiceModel.CFClientBase`1.GetContractSerializer(CFContractSerializerInfo info)
   at Microsoft.Tools.ServiceModel.CFClientBase`1.getResult[TRESPONSE](Message reply, CFInvokeInfo info)
   at Microsoft.Tools.ServiceModel.CFClientBase`1.Invoke[TREQUEST,TRESPONSE](CFInvokeInfo info, GetPendingActionsRequest request)
   at Motorola.SSP.CF.Communication.DaWebServiceContractClient.GetPendingActions(GetPendingActionsRequest request)
   at Motorola.SSP.CF.Communication.DaWebServiceContractClient.GetPendingActions(String sessionId)
   at Motorola.SSP.CF.Communication.DaCommClient.ClientThread()

My application literally does nothing else besides calling this one function.

Any help would be appreciated!
0
Comment
Question by:axnst2
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
8 Comments
 
LVL 25

Expert Comment

by:apeter
ID: 39782305
Please past the wcf code, so that we see whether are there any memory leaks. Like threads, DB connections, file access etc.
0
 

Author Comment

by:axnst2
ID: 39782315
I assume that you'd like to see the client side code since that's where I'm getting the exception, correct?
0
 

Author Comment

by:axnst2
ID: 39782385
Here's the client code:

Please keep in mind that the client is running on Windows Mobile (.NET CF 3.5)

public partial class Form1 : Form
    {
        DaCommClient _DAClient = null;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                if (_DAClient == null)
                {
                    _DAClient = new DaCommClient("192.168.1.150", 9091, new System.Version("1.0.0.0"));
                }

                _DAClient.ValidateLicense(new Guid("00000000-4CCC-15E1-282C-9486E71E71C6"));

            }
            catch (Exception er)
            {
                MessageBox.Show(er.ToString());
            }
        }
    }

public class DaCommClient : IDisposable
    {
        // internal fields
        private object _communicationLock = new object();
        private DaWebServiceContractClient _webService;
        private Thread _clientThread;
        private bool _shutdownThread;
        private Guid _uii;
        private string _serverAddress;
        private int _serverPort;
        private int _serverQueryInterval;
        private Guid _conectedDeviceComponentType = Guid.Empty;

        private string _sessionId = string.Empty;
        private static System.Version _applicationVersion = null;        

        public DaCommClient(string serverAddress, int serverPort, System.Version currentApplicationVersion)
        {
            _applicationVersion = currentApplicationVersion;

            // validate our params
            if (string.IsNullOrEmpty(serverAddress)) throw new ArgumentException("Server address is required and cannot be null or empty.");
            if (serverPort < 1 && serverPort > ushort.MaxValue) throw new ArgumentException("Server port is invalid. Must be between 1 and " + ushort.MaxValue);

            // initialize
            _serverAddress = serverAddress;
            _serverPort = serverPort;
            _serverQueryInterval = 500;

            // create the web service
            BasicHttpBinding binding = new BasicHttpBinding();
            binding.MaxReceivedMessageSize = 1024 * 1024;
            string address = string.Format("http://{0}:{1}/SSP/DA/Web", _serverAddress, _serverPort);
            _webService = new DaWebServiceContractClient(binding, new EndpointAddress(address));
            
        }

        public void Dispose()
        {
            Close();
        }
        
        public bool ValidateLicense(Guid uii)
        {
            lock (_communicationLock)
            {
                _uii = uii;
                if (StartNewSession())
                {
                    // start the client thread
                    _shutdownThread = false;
                    _clientThread = new Thread(new ThreadStart(ClientThread));
                    _clientThread.Start();

                    return true;
                }
                else
                {
                    return false;
                }
            }
        }

        public void Close()
        {
            // shutdown the thread
            if (_clientThread != null)
            {
                // stop the main thread
                _shutdownThread = true;
                if (!_clientThread.Join(5000))
                {
                    _clientThread.Abort();
                }
            }
        }

        private void ClientThread()
        {
            // set the connection state

            while (!_shutdownThread)
            {
                MobileClientPendingAction[] actions = null;

                try
                {
                    lock (_communicationLock)
                    {
                        actions = _webService.GetPendingActions(_sessionId);
                    }
                }
                catch (CFFaultException ex)
                {
                    FaultMessage msg = new FaultMessage(ex.FaultMessage);
                    if (msg.ErrorCode == FaultErrorCode.InvalidSession)
                    {
                        try
                        {
                            // try to start a new session
                            StartNewSession();
                        }
                        catch (CommunicationException)
                        {
                            // do nothing here
                        }
                    }
                }
                catch (Exception er)
                {
                    throw er;
                }

                // wait before making another request
                SmartSleep(_serverQueryInterval);
            }
        }
        
        private bool StartNewSession()
        {
            lock (_communicationLock)
            {
                try
                {
                    if (_applicationVersion == null)
                    {
                        throw new Exception("Current application version must be set prior to attempting to create a new session");
                    }

                    if (string.IsNullOrEmpty(_sessionId))
                    {
                        _sessionId = _webService.ValidateLicense(_uii.ToString(), "37978D90-FF9D-427A-834D-AB032BADE1ED");
                    }

                    return true;
                }
                catch (CFFaultException ex)
                {
                    FaultMessage msg = new FaultMessage(ex.FaultMessage);
                    if (msg.ErrorCode == FaultErrorCode.NoLicenseAssigned)
                    {
                        if (!string.IsNullOrEmpty(_sessionId))
                        {
                            // raise an event if we had a session
                            _sessionId = null;
                        }

                        return false;
                    }
                    else
                    {
                        throw new CommunicationException(msg.Message);
                    }
                }
                catch (Exception ex)
                {
                    throw new CommunicationException("Error communicating with the server.", ex);
                }
            }

            return false;
        }

        private void SmartSleep(int ms)
        {
            int timeToSleep = ms;
            while (timeToSleep > 0)
            {
                // break early if the thread is being shutdown
                if (_shutdownThread)
                {
                    break;
                }

                Thread.Sleep(100);
                timeToSleep -= 100;
            }
        }

        public static Version Convert(System.Version version)
        {
            Version convertedVersion = new Version();

            convertedVersion._Major = version.Major;
            convertedVersion._Minor = version.Minor;
            convertedVersion._Build = version.Build;
            convertedVersion._Revision = version.Revision;

            return convertedVersion;
        }
    }

Open in new window

0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 25

Expert Comment

by:apeter
ID: 39782941
From the first glance, you are not calling the dispose method of "DaCommClient". Can you please do like below and see it improves ?


private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                if (_DAClient == null)
                {
                    _DAClient = new DaCommClient("192.168.1.150", 9091, new System.Version("1.0.0.0"));
                }

                _DAClient.ValidateLicense(new Guid("00000000-4CCC-15E1-282C-9486E71E71C6"));

            }
            catch (Exception er)
            {
                MessageBox.Show(er.ToString());
            }
            finally
{
 if (_DAClient != null)
                {
                        _DAClient.Dispose();
                  }
        }
0
 

Author Comment

by:axnst2
ID: 39783272
That's not it.  I call Dispose in from_Closing.  Please take a look at the function ValidateLicense.  It starts a baground thread that keeps calling _webService.GetPendingActions over-and-over again (in order to test the issue), and therefore, I don't want to dispose of the client.

I fixed the problem but I don't understand why my fix is a fix.  So instead of using NetCFSvcUtil.exe to generate the web service proxy objects, I simply used the "Add Web Reference" function built into VS2008 (on the client side) and my problem went away.  Can you explain to me why?
0
 
LVL 25

Accepted Solution

by:
apeter earned 2000 total points
ID: 39784789
I don't see the "from_Closing" method. but it is always better to dispose every time a request is made by clicking the button rather than at form closing.


Please check this link to see why the memory problem occurs due the exe, http://social.msdn.microsoft.com/Forums/vstudio/en-US/97b84107-065e-4006-8565-536749349d67/memory-leak-in-windows-mobile-wcf-proxy-client?forum=wcf
0
 

Author Closing Comment

by:axnst2
ID: 39785430
Thank you, the explanation you posted regarding the bug in the NetCFSvcUtil utility explains why adding a "web reference" instead of using the NetCFSvcUtil utility fixed my OutOfMemoryException problem.  It's sad that Microsoft obviously knows about this bug and has done nothing to fix it.  This bug basically renders the utility useless.
0
 

Author Comment

by:axnst2
ID: 39785794
Just as a side note, as an unexpected (but very welcome) side effect, changing from NetCFSvcUtil to the "Add Web Reference" method has DRASTICALLY improved the overall speed of my ENTIRE application, even parts that never even call the web service!!!  :)
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This tutorial will show you how to add an attribute to an XML (http://en.wikipedia.org/wiki/XML) stream returned from a Windows Communication Foundation (http://en.wikipedia.org/wiki/Windows_Communication_Foundation) (WCF) Web Service.  Some knowled…
While working on Silverlight and WCF application, I faced one issue where fault exception occurred at WCF operation contract is not getting propagated to Silverlight client. So after searching net I came to know that it was behavior by default for s…
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …
Please read the paragraph below before following the instructions in the video — there are important caveats in the paragraph that I did not mention in the video. If your PaperPort 12 or PaperPort 14 is failing to start, or crashing, or hanging, …
Suggested Courses

618 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question