Avatar billede jess_chr Nybegynder
05. april 2005 - 08:21 Der er 21 kommentarer

Begrænsning af CPU usage i threads

jeg har langt om længe fået lært mig selv noget om threads, men problemet er at når jeg kører en uendelig løkke i en thread, i et lille UDP Chat program jeg har sat sammen, sluger programmet omkring 50% af min CPU!

det virker... men det er ikke helt hvad jeg havde håbet på!

Spørgsmålet er om der er nogen der har en ide om hvordan man kan begrænse programmet således det ikke sluger alt min processor kraft... jeg har googlet efter det, samt kigget herinde på eksperten, men faktum er at jeg ikke ved hvad jeg leder efter.

jeg sætter min lid til eksperterne... Tak
Avatar billede spif2001 Nybegynder
05. april 2005 - 08:26 #1
Du kan sætte prioriteten på tråden således:

Thread t = new Thread(new ThreadStart(Run));
t.Priority = ThreadPriority.Lowest;
Avatar billede spif2001 Nybegynder
05. april 2005 - 08:26 #2
Så får alle andre tråde med højere prioritet mere at sige hos scheduler'en
Avatar billede arne_v Ekspert
05. april 2005 - 08:33 #3
Lyder som om du har et loop som ikke blocker.

Du bør redesigne. Det er kun en workaround at sænke prioritet.

Umiddelbart vil jeg tro at du skal have et loop som læser UDP datagrams
blocking og enqueuer til en queue, hvor et antal threads blocking
dequeer og processer.
Avatar billede md_craig Nybegynder
05. april 2005 - 09:17 #4
Hvad form for Threads bruger du desuden ?
Dedicated eller Pooled(Delegates) ???
Avatar billede jess_chr Nybegynder
05. april 2005 - 09:41 #5
som sagt lærer jeg efter krav men jeg er ret sikker på at de er pooled, og nej looped blocker ikke, jeg begyndte på det her i sidste uge... og har optil nu sagt at hvis det virker så er det det...

UDP datagrams, er store ord jeg er ikke så hardcore til det her endnu. jeg prøver lige ThreadPriority metoden!
Avatar billede jess_chr Nybegynder
05. april 2005 - 10:26 #6
ThreadPriority.Lowest virkede ikke, jeg har kun en enkelt tråd med en uendelig løkke. så selv om den er lowest priority anvender den stadig alle 50 procent.

Men hvordan kan man gøre, således løkken kun køre når der sendes eller der skal modtages... at sende er ikke noget problem, men jeg anvender løkken til at tjekke efter ny data!
Avatar billede lifo Nybegynder
05. april 2005 - 10:39 #7
en metode jeg bruger i mit eget chat program

public void lytEfterKliente()
{
  lytteSocket = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
  try
  {
  IPEndPoint iep = new IPEndPoint(IPAddress.Any,_port);
  lytteSocket.Bind(iep);
  while(_running)
  {
    EndPoint ep = iep;
    byte[] data = new byte[1500];
    int recv = lytteSocket.ReceiveFrom(data,ref ep);//<--- står og venter til data kommer
    byte[] tmp = new byte[recv];
    for(int i =0;i<recv;i++)
    {
    tmp[i]=data[i];
    }
  // nu har du dine data i tmp


}
}
catch(ThreadAbortException ex)
{
  log.Debug("lytte tråd er aborted"+ex.Message);   
}
catch(SocketException ex)
{
log.Error("Socket fejl i lytefterkliente",ex);
}
catch(Exception ex)
{
log.Error("Exception i     "+ex);
}
finally
{
lytteSocket.Close();
}
}
Avatar billede jess_chr Nybegynder
05. april 2005 - 11:40 #8
Det ser ikke helt dårligt ud lifo... jeg kan eventuelt anvende den som event til at starte min egen lyttetråd, men jeg får nogle fejl fra "lyttesocket" samt "_port" og "_running"...

jeg kunne ikke tilfældigvis lige få dig til at skrive hvad det er?

fx om det er en bool osv...
Avatar billede md_craig Nybegynder
05. april 2005 - 15:06 #9
jess_chr >>

Hvis du bruger Delegates er det Pooled Threads.... (bruger du keyworded delegate nogen steder)
Men så kan du ikke prioritere dine Threads
Avatar billede lifo Nybegynder
05. april 2005 - 15:32 #10
_port er bare en lokal int som definerer hvad port jeg skal lytte på
til mit chat program som er en klon af Vypress Chat bruger jeg port 8167

lyttesocket er et Socket objekt
_running er bare en bool

jeg har en metode som hedder startToListen

public void startToListen()
{
if(!_running)
{
_running = true;
lytteThread = new Thread(new ThreadStart(lytEfterKliente));
lytteThread.Name="Lytte Thread";
lytteThread.IsBackground=true;
lytteThread.Start();
}
}

så bruger jeg desuden events til at sende data videre

men om du vil så kan du godt få hele koden til mit chat program
Avatar billede jess_chr Nybegynder
06. april 2005 - 09:40 #11
til md craig: Jeg har som sagt kun en enkelt thread, så tænkte jeg nok at den nok ikke ville virke blot at sætte priorities...

Og jeg ved faktisk ikke hvad "keyworded delegates" er så jeg kunne ikke forestille mig at jeg brugte dem.

til lifo: hele koden ville ikke være dårligt, det kunne være jeg fangede tricket i at undgå de uendelige løkker jeg anvender lige nu...

Jeg kiggede i den kode du skrev igår og fik det også til at virke, men den er næsten(alt er relativt) magen til min egen kode så spørgsmålet har nok ændret sig til "Hvordan du kører dine metoder, uden at anvende de uenelige løkker som sagt!"!
Avatar billede arne_v Ekspert
06. april 2005 - 09:43 #12
Der er ikke noget galt i en uendelig løkke i en server app.

Den skal bare lave blocking read.
Avatar billede jess_chr Nybegynder
06. april 2005 - 09:49 #13
men hvordan laver man den "Blocking read"... kan du give et eksempel?
Avatar billede arne_v Ekspert
06. april 2005 - 09:54 #14
ReceiveFrom blocker
Avatar billede arne_v Ekspert
06. april 2005 - 10:03 #15
medmindre du laver:

dinsocket.Blocking = false;
Avatar billede jess_chr Nybegynder
06. april 2005 - 11:01 #16
jeg er desværre ikke garevt nok til at sige jeg har brugt det du skriver om før... kan du give et hint mere?
Avatar billede lifo Nybegynder
06. april 2005 - 11:14 #17
en helt anden mulighed er at det ikke er din kode som henter data der bruger cpu kræfterne

når du bruger tråde skal du være meget opmærksom på at du ikke kan opdatere din GUI direkte fra en anden tråd

en god ide ville være at lære lidt om Delegates og events
og i forbindelse med tråde om InvokeRequired/Invoke
Avatar billede jess_chr Nybegynder
06. april 2005 - 12:23 #18
jeg er helt hundrede på at det er tråden jeg anvender til at lytte på netværket der bruger CPU kræfterne, da det ikke er første gang jeg anvender denne slags tråd...

og jeg kan godt anvende GUI'en fra min tråd da jeg har lavet den direkte i i min form klasse...

i tilfælde af tvivl ser koden således ud...

  Thread dost = new Thread(new ThreadStart(dostuff));
  dost.Start();

den er ikke kørt i et nyt objekt...
Avatar billede md_craig Nybegynder
06. april 2005 - 12:47 #19
Ja så er den dedikeret... ;)

Hvis du ønsker at bruge delegates foregår det på denne måde:
_____________________________________________________________________________________

public class WorkerClass
{
  private volatile bool abort;

  delegate void UDPListenerDelegate();

  public void OnStart()
  {
    UDPListenerDelegate udpld = new UDPListenerDelegate(Working);
    udpld.BeginInvoke(new AsyncCallback(OnComplete), this);
  }

  public void Working()
  {
    while(!abort)
    {
    //Do some work
    ...
   
    //ThreadSleep 100 ms
    Thread.Sleep(100);
    }
  }

  public void OnComplete(IAsyncResult iar)
  {
    //Cleanup kode her

    AsyncResult ar = (AsyncResult) iar;
    RunWorkerDelegate rwd = (RunWorkerDelegate) ar.AsyncDelegate;
   
    rwd.EndInvoke(iar);
  }
}
_____________________________________________________________________________________

Det var så et grund skelet...
Man kan også have parametre med i de forskellige metode og man kan kalde metoderne hvad man vil... og du kan desuden sagtens have flere delegates i en klasse...
Avatar billede md_craig Nybegynder
06. april 2005 - 12:49 #20
hehe... der var lige lidt fejl... sådan kan det gå når man CopyPaster :P
_____________________________________________________________________________________

public class WorkerClass
{
  private volatile bool abort;

  delegate void UDPListenerDelegate();

  public void OnStart()
  {
    UDPListenerDelegate udpld = new UDPListenerDelegate(Working);
    udpld.BeginInvoke(new AsyncCallback(OnComplete), this);
  }

  public void Working()
  {
    while(!abort)
    {
    //Do some work
    ...
   
    //ThreadSleep 100 ms
    Thread.Sleep(100);
    }
  }

  public void OnComplete(IAsyncResult iar)
  {
    //Cleanup kode her

    AsyncResult ar = (AsyncResult) iar;
    UDPListenerDelegate rwd = (UDPListenerDelegate) ar.AsyncDelegate;
   
    rwd.EndInvoke(iar);
  }
}
Avatar billede lifo Nybegynder
06. april 2005 - 19:37 #21
jess_chr skrev
og jeg kan godt anvende GUI'en fra min tråd da jeg har lavet den direkte i i min form klasse...

det er lige meget hvor du laver din tråd bare du har flere tråde så kan det gå galt
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester