[C#/WCF]Memory leak bij gebruik ServiceClient

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Topicstarter
Ik ben bezig met een applicatie die een WCF webservice consumeert. Elke paar seconden wordt er een WebMethod aangeroepen. Ik loop nou echter tegen het probleem aan dat ik een geheugenlek heb. Na verloop van tijd wordt er steeds meer unmanaged geheugen gebruikt, tot er op een gegeven moment een OutOfMemoryException komt.

Ik heb een test programma gemaakt waarbij exact hetzelfde probleem optreedt.

Om de server te consumeren heb ik de volgende code
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
while (true)
{
    var binding = new WebHttpBinding { OpenTimeout = new TimeSpan(0, 0, 0, 2) };
    var client = new MyServiceClient(binding,
                                                new EndpointAddress("http://server/path/"));
    try
    {
        var result = client.Foo("BAR");
        client.Close();
    }
    catch (Exception ex)
    {
        client.Abort();
    }
    finally
    {
        ((IDisposable)client).Dispose();
    }
}

[ServiceContract, XmlSerializerFormat]
public interface IFoo
{
    [OperationContract]
    [WebInvoke(Method = "GET",
        ResponseFormat = WebMessageFormat.Xml,
        BodyStyle = WebMessageBodyStyle.Wrapped,
        UriTemplate = "{bar}")]
    List<Bar> Foo(string bar);
}

public class MyServiceClient: ClientBase<IFoo>, IFoo
{
    public MyServiceClient(Binding binding, EndpointAddress remoteAddress)
        : base(binding, remoteAddress)
    {
        Endpoint.Behaviors.Add(new WebHttpBehavior());
    }

    public List<DocumentElement> Foo(string bar)
    {
        return Channel.Foo(bar);
    }
}

Heeft er iemand enig idee wat ik fout doe waardoor er unmanaged geheugen weglekt?

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Merethil
  • Registratie: December 2008
  • Laatst online: 17:00
Klinkt in mijn oren als:
- óf de client wordt niet juist opgeruimd na de aanroep en afhandeling,
- óf de List-objecten die je maakt met je client.Foo("BAR") worden niet juist weggegooid achteraf en dus opgeslagen in een deel van je geheugen, wat na een tijdje ervoor zorgt dat je hele geheugen vol staat met nieuwe lists.

Ruim je de result weer op achteraf? Of wordt dit ergens anders nog gebruikt verderop in de code?
Misschien is de aanroep alweer gebeurd omdat je while(true) gebruikt en dus de volgende call al is gedaan ook al ben je verderop in de code nog bezig met result?

Acties:
  • 0 Henk 'm!

  • BasieP
  • Registratie: Oktober 2000
  • Laatst online: 22-07-2024
Ik neem aan dat je niet zelf geheugen alloc-t. Zou het kunnen dat je een aantal disposable types gebruikt die je disposed?

(ow en kijk eens naar het 'using' statement)

[ Voor 16% gewijzigd door BasieP op 11-04-2013 15:24 ]

This message was sent on 100% recyclable electrons.


Acties:
  • 0 Henk 'm!

  • Daspeed
  • Registratie: Maart 2001
  • Laatst online: 19-07 19:12

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Topicstarter
Merethil schreef op donderdag 11 april 2013 @ 15:20:
Klinkt in mijn oren als:
- óf de client wordt niet juist opgeruimd na de aanroep en afhandeling,
In mijn testcase wordt netjes de Close en daarna nog Dispose van de serviceclient aangeroepen, dus ik zou niet weten wat ik nog meer op zou moeten ruimen.
- óf de List-objecten die je maakt met je client.Foo("BAR") worden niet juist weggegooid achteraf en dus opgeslagen in een deel van je geheugen, wat na een tijdje ervoor zorgt dat je hele geheugen vol staat met nieuwe lists.
Mijn testcode is exact wat ik hierboven heb staan, ik gebruik de list in mijn testcase verder niet eens, dus hij gaat gewoon out of scopen. Maar als dat het geval zou zijn zou het ook niet om unmanaged geheugen gaan.
BasieP schreef op donderdag 11 april 2013 @ 15:23:
Ik neem aan dat je niet zelf geheugen alloc-t. Zou het kunnen dat je een aantal disposable types gebruikt die je disposed?
De code die ik hier toon is mijn complete testcase. Alleen de Datacontract definitie heb ik er niet bij staan, maar die bevast niks speciaals met geheugen allocatie o.i.d.
(ow en kijk eens naar het 'using' statement)
Ik weet prima hoe het using statement werkt, maar dat is niet aan te raden bij het gebruik van WCF clients. ( De Dispose kan weer een exception gooien als de client in Faulted state is ).

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Topicstarter
Kijk dat ziet er inderdaad interessant uit, op die pagina was ik met mijn zoektoch nog niet terecht gekomen.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • D-Raven
  • Registratie: November 2001
  • Laatst online: 07-07 14:42
wtf.. die kende ik nog niet..
Ik wist wel van die XmlSerializer bug, maar ik heb m nog niet icm WCF gezien. Ik nam aan dat ze daar in ieder geval wel de juiste constructor gebruiken. Blijkbaar niet...

Bedenk me nu dat ik m nog niet ben tegengekomen omdat ik overal de DataContractSerialiser gebruik.
Maar aangezien jij specifiek in xml formaat terug geeft, gaat dat lastig worden :P.

* D-Raven gebruikt WCF niet als rest service
overkill en veel te complex voor iets wat ik met webapi of vanilla asp.net mvc veel makkelijker kan oplossen imho.

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Topicstarter
Dit was inderdaad het probleem, door gebruik te maken van de DatacontractSerializer verdwijnt het probleem als sneeuw voor de zon. Gelukkig was de interface specificatie niet zo hard dat er geen kleine tweaks gedaan konden worden, anders had ik nog weer een uitdaging gehad om exact hetzelfde XML formaat te krijgen.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”

Pagina: 1