Endlos Backgroundworker memory problem
-
Hi,
ich habe da ein programm(in VB) dass eine überwachung endlos ausführen soll, dazu verwende ich den backgrounworker der dann alle 35 sec (Thread.sleep) die prozedur ausführt.
Es funktioniert alles wunderbar, doch habe ich das problem dass sich das ding nach 4-5 tagen abschiesst da die speicherauslastung kontinuierlich anwächst und das system irgendwann den prozess beendet.
Warum wächst die Speicherauslastung obwohl das ding im hintergrund läuft ?
Wie kann man sowas beheben ?
Habe es schon mit garbage collector aufrufen und dispose probiert doch das geht alles nicht und dispose geht nur wenn ich die form schliesse .
THANNX
CU
-
Es ist wichtig, dass Du weisst, wann Objekte vom GC freigegeben werden können.
Lies Dich in das Thema ein.- Ein berühmter Kandidat für Memory Leaks unter .NET ist das event- Handling.
- Ein zweiter Kandidat wäre eine fehlender Aufruf der Endxxx(..) Methoden bei asynchronen Operation (durch Beginxxx(..) gestartet). Hier gehts um Handle Leaks.Benutze Tools um die Memory Leaks zu finden.
Z.B. VS2005 od. VS2008 (ab Team System)
http://www.microsoft.com/germany/msdn/vstudio/products/produktvergleich.mspxOd. den DevPartner von Compuware...
Hier sind noch ein wertvoller Anhaltspunkt:
http://msdn2.microsoft.com/en-us/library/ms954591.aspxGruss Simon
-
Zeige doch mal Code her. Ev. sticht etwas gerade ins Auge...
-
[edit]ich tipp zu langsam[/edit]
-
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Try worker = New System.ComponentModel.BackgroundWorker() worker.WorkerReportsProgress = True worker.WorkerSupportsCancellation = True AddHandler worker.DoWork, New _ System.ComponentModel.DoWorkEventHandler(AddressOf OnWork) worker.RunWorkerAsync() Catch ex As Exception Sleep(10000) logfile.WriteLine("Date: " & now & " WorkerError: " & ex.Message) logfile.Flush() logfile.Close() End Try End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Me.Close() End Sub Private Sub DoWork(ByVal Sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) End Sub Private Sub OnWork(ByVal sender As Object, _ ByVal e As System.ComponentModel.DoWorkEventArgs) Try If worker.CancellationPending = True Then 'e.Cancel = True Exit Sub End If ...... Sleep(35000) 'OnWork(sender, e) DoWork(sender, e) Else Sleep(35000) 'OnWork(sender, e) DoWork(sender, e) End If Catch ex As Exception Sleep(10000) logfile.WriteLine("Date: " & now & " " & ex.Message) logfile.Flush() logfile.Close() Finally 'Sleep(30000) 'OnWork(sender, e) DoWork(sender, e) End Try End Sub
-
Auf den ersten Blick sehe ich keine Probleme.
Hast Du die Probleme auch mit leerer OnWork Methode?
-
bis jetzt war die leer, jetzt probiere ich grad dass in der dowork dann der Onwork aufruf ist und es scheint besser zu werden.
sieht so aus als ob er langsam anwächst aber dann auf einmal wieder auf 700k runter geprügelt wird.
das komische ist auch ich habe es parallel auf nem anderen rechner laufen und da wächst es nicht an !(noch mit der leeren dowork)
naja mal beobachten
THANXX
anyway
CU
-
Es ist so, dass der Memory Verbrauch ruhig ansteigen darf.
Es ist ja der GC involviert und der macht seine Arbeit korrekt.Wenn ich dich richtig verstanden habe, wird es ohne den Code von DoWork besser, oder?
Was ist das für Code?Simon
-
ne ne ich hatte vorher ja unten dann den aufruf
OnWork(sender, e)
jetzt läuft´s grad mit DoWork(sender, e) und der ruft dann den OnWork auf.
Habe irgendwo gelesen dass es probleme geben kann wenn man den Onwork aus sich heraus aufruft.und wie gesagt hatte es mal 4 tage laufen und da war der speicher dann auf 85000 K und das ding stürzte dann irgendwann ab.
kann es auch an den rechten liegen ? bin hier grad lokaler admin und auf der anderen kiste als user angemeldet ?
oder kann es mit dem leerlaufprozess zusammen hängen ? (die kiste stand ja 4 tage still)CU
-
Ich nehme an Du hast noch nicht gedebuggt, wenn ein Fehler aufgetreten ist. Wäre ja mühsam so lange zu warten.
Nun, wenn ich dich recht verstanden habe, dann ruft OnWork die Methode DoWork auf, welche wiederum OnWork aufruft, usw.
Vereinfacht so, natürlich mit Abbruch Kriterium und den Sleep's.
Edit: (Sorry habs nur in C#)using System; using System.Windows.Forms; using System.ComponentModel; namespace Test { public partial class MainForm : Form { private BackgroundWorker worker = new BackgroundWorker(); public MainForm() { InitializeComponent(); } private void Button1Click(object sender, EventArgs e) { worker.DoWork += new DoWorkEventHandler(OnWork); worker.RunWorkerAsync(); } private void DoWork(object sender, DoWorkEventArgs e) { DoWork(sender, e); } private void OnWork(object sender, DoWorkEventArgs e) { OnWork(sender, e); } } }
Dies verrusacht einen Stackoverflow, weil es ein Rekursiver Aufruf ist.
Gruss Simon
-
Du kannst das einfach testen, indem Du alle Sleeps rausnimmst und nur noch die gegenseitigen Aufrufe drin lässt. Dann passiert nämlich genau das, was mit den Sleeps 4-5 Tage dauert, innert (milli) sekunden.
-
ja denke auch dass es daran lag.
bis jetzt war es so dass onwork sich immer wieder aufgerufen hat und Dowork eben nix gemacht hat.
jetzt ruft onwork dowork auf und das ruft onwork wieder auf und nun scheint´s zu passen.
CU
-
jetzt ruft onwork dowork auf und das ruft onwork wieder auf und nun scheint´s zu passen.
Was heisst passen?
Wenn OnWork -> DoWork -> OnWork -> DoWork -> ... ist es überhaupt nicht besser als OnWork -> OnWork -> OnWork -> ...Es gibt eine StackOverflowException !
-
hmm eben nicht. jetzt wächst der speicher an und wird dann wieder nach einiger zeit reduziert.
liegt glaub ich daran:
worker = New System.ComponentModel.BackgroundWorker() AddHandler worker.DoWork, New _ System.ComponentModel.DoWorkEventHandler(AddressOf OnWork)
CU
-
ABstraCT schrieb:
liegt glaub ich daran:
worker = New System.ComponentModel.BackgroundWorker() AddHandler worker.DoWork, New _ System.ComponentModel.DoWorkEventHandler(AddressOf OnWork)
CU
Also an was jetzt genau von dem Code?
Das machst Du doch nur einmal zu Begin, oder?
-
hmm ich glaub ich habe da eh nen denkfehler drin !
irgendwie dachte ich mann muss die onwork immer wieder aufrufen aber eigentlich reicht es ja alles dann in ner schleife mit den sleeps ablaufen zu lassen ohne irgendwas wieder aufrufen zu müssen.CU
-
Ja, dann wird aus der rekusion eine iteration und das ist sehr viel besser im hinblick auf die StackOverflowException.
Grüsse
Simon
-
ABstraCT, Du zeigst uns das Skelett und wir sollen die Leber untersuchen?
Wenn ich mir das so anhöre, könnte ich wetten, dass Du sowohl in DoWork als auch in OnWork direkt auf Instanz-Variablen zugreifst. Stimmt das? Well, in diesem Fall scheppert das Design Deiner Anwendung ganz laut. Und die Idee mit den Sleeps beeinträchtigt die Performanz des ganzen Systems. Verwende Timer. New-e deine Variablen in WorkerThread. Und nach Ablauf einer Arbeitsrunde verwende:
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
Der GC macht seine Arbeit ganz gut. Wenn er nur dazu kommen darf. Und was der Task-Manager über den Verbrauch von Speicher sagt, ist nicht immer wörtlich zu nehmen. Woher weißt Du überhaupt, dass dein Programm ein Speicher-Problem hat? Wirft die Anwendung einen Ausnahmefehler (MemoryOutofRangeException, OutOfMemoryException usw.)? Verwendest Du System-Ressourcen (Handles etc.)? Wenn es einen Crash gibt, was steht dann im System-Log?
Fragen über Fragen. Poste wirklichen Code und wirkliche Fehlermeldungen, dann kann Dir vielleicht auch wirklich geholfen werden.
-
Wieso beeinflusst das Sleep das gesamte System ?
-
maro158 schrieb:
ABstraCT, Du zeigst uns das Skelett und wir sollen die Leber untersuchen?
Wenn ich mir das so anhöre, könnte ich wetten, dass Du sowohl in DoWork als auch in OnWork direkt auf Instanz-Variablen zugreifst. Stimmt das? Well, in diesem Fall scheppert das Design Deiner Anwendung ganz laut. Und die Idee mit den Sleeps beeinträchtigt die Performanz des ganzen Systems. Verwende Timer. New-e deine Variablen in WorkerThread. Und nach Ablauf einer Arbeitsrunde verwende:
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
Der GC macht seine Arbeit ganz gut. Wenn er nur dazu kommen darf. Und was der Task-Manager über den Verbrauch von Speicher sagt, ist nicht immer wörtlich zu nehmen. Woher weißt Du überhaupt, dass dein Programm ein Speicher-Problem hat? Wirft die Anwendung einen Ausnahmefehler (MemoryOutofRangeException, OutOfMemoryException usw.)? Verwendest Du System-Ressourcen (Handles etc.)? Wenn es einen Crash gibt, was steht dann im System-Log?
Fragen über Fragen. Poste wirklichen Code und wirkliche Fehlermeldungen, dann kann Dir vielleicht auch wirklich geholfen werden.
Es hat sich doch schon gestern geklärt das es kein Speicherproblem sondern ein Stack Overflow war ausgelöst durch eine endlos rekursion.