Re: Problem GUI-Loop-CPU Auslastung

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance

From: Frank Dzaebel (Post_at_FranksSeite.de)
Date: 03/03/05


Date: Fri, 4 Mar 2005 00:01:55 +0100

Hallo Olli,

> Mit einem Button auf der Mainform werfe ich den Loop an. Dieser arbeitet
> bis zum beenden und liefert mir meine Counter. Waehrend des loops ist
> meine CPU-Auslastung ca. bei 2-4 %. Klicke ich nur einmal die Form direkt
> an (z.B. Titelbar) oder verschiebe diese am Desktop und starte danach den
> Loop dann habe ich ploetzlich eine CPU-Auslastung nahe der 95%.

Also zunächst einmal ist es eine Standard-Einstellung für Windows-PCs, dass
diese ihre Vordergrund-Applikationen höher 'priorisieren' (intern über
Zeitscheiben-Quantum).
Dies kann auch verändert werden auf Hintergrund-Tasks, ist aber eine
System-weite Einstellung und ist auch OS-abhängig.
http://support.microsoft.com/kb/259025/en-us
Deswegen wird z.B. u.a. bei Klick-Aktivierung/Fenster-Verschiebung einer
Form normal die CPU-Usage für diesen Prozess und global höher.
[-> Process.PriorityBoostEnabled-Eigenschaft]
http://msdn.microsoft.com/library/deu/cpref/html/frlrfsystemdiagnosticsprocessclasspriorityboostenabledtopic.asp

Ein andere Sache ist Deine Loop.
Zwar wurde hier schon Application.DoEvents() vorgeschlagen, aber das ist oft
ein Workaround für eine sauberere Thread-Lösung.
Ich reisse das Thema mal oberflächlich an :

Im folgenden Beispiel werden 2 Threads gestartet. Der eine macht die Arbeit.
Der andere kümmert sich darum, dass Events verarbeitet werden, indem er
(ständig) den ersten suspended, Thread.Sleep(1) aufruft und dann den ersten
wieder resumed.
Dadurch wird die CPU-Usage des Gesamt-Prozesses sehr klein gehalten
(speziell Thread1).
(Die "TextBoxX.Text = Y" - Zeilen müßten eigentlich über InvokeRequired
aufgerufen werden)

Thread t1;
private void btnCpuUsage_Click(object sender, System.EventArgs e)
{
  // DoHardWork(); // So (alleine würden keine Events verarbeitet)
  t1 = new Thread(new ThreadStart(DoHardWork)); t1.Start();
  new Thread(new ThreadStart(MessageThread)).Start();
}

private void MessageThread()
{
  long count2 = 0;
  while (!t1.IsAlive) Thread.Sleep(1);
  while (t1.IsAlive)
  {
    if (t1.IsAlive) t1.Suspend();
    Thread.Sleep(1);
    if (t1.IsAlive) t1.Resume();
    count2++ ;
  }
  textBox2.Text = "count2="+ count2.ToString() +
    "\r\nEnded:" + DateTime.Now.ToLongTimeString();
}

private void DoHardWork()
{
  Cursor = Cursors.WaitCursor;
  long count1 = 0;
  DateTime Start = DateTime.Now;
  while ((DateTime.Now-Start).Seconds < 5)
  {
    Math.Sin(5.0d);
    // if (count % 0xFFFF == 0) Thread.Sleep(1);
    count1++ ;
  }
  Cursor = Cursors.Default;
  textBox1.Text = "count1="+ count1.ToString() +
    "\r\nStarted:" + Start.ToLongTimeString() +
    ", Ended:" + DateTime.Now.ToLongTimeString();
}

Dies wäre ein generischer Ansatz letztlich über OS-Time-Slicing.
Stattdessen kann auch innerhalb von DoHardWork() Thread.Sleep(1)
aufgerufen werden. Das wäre eine Verbesserung der Performance.
(Siehe die auskommentierte Zeile)
Übrigens benutzt auch die CLR selber letztlich Thread.Sleep(1) in
seinem Message-Dispatcher
(-> SystemEvents.WindowThreadProc: undokumentiert).

ciao Frank

--
Dipl.Inf. Frank Dzaebel [MCP C#]
http://Dzaebel.NET 


Relevant Pages

  • RE: Oracle cursor help
    ... rids dbms_utility.uncl_array; ... where <your where clause> ... Subject: Re: Oracle cursor help ... exit the loop: */ ...
    (perl.dbi.users)
  • Re: S-expression I/O in Ada
    ... The limited interface long with the Container objects make me pretty ... No_Element: constant Cursor; ... function To_String(Position: in Cursor) return String; ... for i in Image'Range loop ...
    (comp.lang.ada)
  • Command object stops prematurely without error?
    ... However, when run via the ADO Command object, the outer loop Applications ... Declare cApps CURSOR for Select ApplicationID from UCM_Applications ...
    (microsoft.public.data.ado)
  • Re: Calling a SP inside a cursor loop..
    ... every loop iteration of the cursor. ... Fetch next From EffectiveDate_Cursor Into @FLD1,@FLD2 ... and If the Fetch stmt is below the begin Stmt, the loop iterations are ... the proper way to program a cursor loop is: ...
    (comp.databases.ms-sqlserver)
  • Re: => Trigger to split Trailer Loads
    ... I am using a Trigger and a cursor with a while loop, however the recursive behaviour of the cursor is causing me ... I can successfully copy an order from tblOrders to tblSplitOrders, duplicating order details and splitting the load into ... Enters LineSplit>0 ...
    (microsoft.public.sqlserver.mseq)