AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Fraktalrechner mit Thread(s) macht Unfug

Ein Thema von everdream · begonnen am 17. Apr 2008 · letzter Beitrag vom 18. Apr 2008
 
Benutzerbild von everdream
everdream

Registriert seit: 22. Feb 2007
Ort: Hiddenhausen
192 Beiträge
 
Delphi 2005 Personal
 
#1

Fraktalrechner mit Thread(s) macht Unfug

  Alt 17. Apr 2008, 23:12
Hallo,

ich wollte meinen kleinen Fraktal-Visualisierer auf Threads umstellen, um meinen DualCore nutzen zu können. Das Programm erstellt eine Reihe von Bitmaps, die man dann zu einem Video konvertieren kann. Am Ende hat mein ein Video, das in das Mandelbrot Fraktal hineinzoomt.
Ich habe mich an das Tutorial "Threads mit Delphi" von Luckie gehalten, aber schon bei einem Thread gibt es große Schwierigkeiten. Folgendes ist mir schon untergekommen (ohne, dass ich zwischendurch das Programm neu kompiliert oder etwas im Code geändert habe):

• Das Bild steht still, keine Zoombewegung
• Das Bild wird nur am linken Rand etwas bemalt, der Rest bleibt weiß
• Es gibt eine Exception "Ungültiges Handle", was sich auf das Thread Handle bezieht
• Es läuft alles ganz normal

Diese Dinge treten meißtens irgendwann während der Berechnung auf (jedoch relativ schnell, nach einigen Dutzend Frames), können aber auch mal beim ersten Durchlauf erscheinen.

Ich muss viele Parameter an den Thread übergeben, habe es aber wie im Tutorial beschrieben gemacht. Am besten zeige ich mal den betreffenden Code:
Delphi-Quellcode:
type
  TThreadParams = packed record
  public
    Center_x, Center_y, Range_x, Range_y, dx, dy, MaxValue: extended;
    MaxIterations, Counter: integer;
    Bitmap: TBitmap;
  end;

  PThreadParams = ^TThreadParams;

//[...]

procedure TMandelbrotSet.SaveSetZoom;
var
  counter: integer;
  dx, dy: extended;
  Parameter: TThreadParams;
  Thread: THandle;
  ThreadID: Cardinal;
  Bitmap: TBitmap;
begin
  // Parameter initialisieren
  counter:=1;
  Bitmap:=TBitmap.Create;
  Bitmap.Width:=x; // Konstante
  Bitmap.Height:=y; // Konstante
  Range_x:=4;
  Range_y:=3;
  dx:=Range_x / x;
  dy:=Range_y / y;
  maxIterations:=200;

  // Konstante Parameter einmalig setzen (gehören zu TMandelbrotSet (privat) und sind initialisiert)
  Parameter.MaxValue:=MaxValue;
  Parameter.Center_x:=Center_x;
  Parameter.Center_y:=Center_y;
  Parameter.Bitmap:=Bitmap;

  // Prozesspriorität verringern, um andere Programme nicht zu "stören"
  SetPriorityClass(GetCurrentProcess, IDLE_PRIORITY_CLASS);

  while (Range_x>0.0000001) do
  begin
    // Aktuelle Parameter für Thread übernehmen
    Parameter.Range_x:=Range_x;
    Parameter.Range_y:=Range_y;
    Parameter.dx:=dx;
    Parameter.dy:=dy;
    Parameter.MaxIterations:=MaxIterations;
    Parameter.Counter:=Counter;

    // Thread erzeugen
    Thread := BeginThread(nil, 0, @ThreadFunc, @Parameter, CREATE_SUSPENDED, ThreadID);
    // Threadpriorität und gewünschten Prozessor setzen
    SetThreadPriority(Thread, THREAD_PRIORITY_IDLE);
    SetThreadIdealProcessor(Thread, 0);
    // Thread starten
    ResumeThread(Thread);

    // Parameter für nächsten Frame setzen:
    Range_x:=Range_x*0.95;
    Range_y:=Range_y*0.95;
    dx:=Range_x / x;
    dy:=Range_y / y;
    maxIterations:=round(200+(Counter*1.2));
    Inc(Counter);

    Application.ProcessMessages;

    // Auf Thread warten
    WaitForSingleObject(Thread, INFINITE);
    CloseHandle(Thread);
  end;
  
  Bitmap.Free;

  // Priorität auf Standard zurücksetzen
  SetPriorityClass(GetCurrentProcess, NORMAL_PRIORITY_CLASS);
end;
und die ThreadFunc:
Delphi-Quellcode:
function ThreadFunc(Params: PThreadParams): Cardinal;
var
  fBitmap: TBitmap;

  fMaxIterations, fIterations, fAverage, fPxl_x,
  fPxl_y, fi, fj, fcounter: integer;

  fx0, fx1, fy1, fCenter_x, fCenter_y, fRange_x, fRange_y,
  fRealC, fImagC, fMaxValue, fdx, fdy: extended;

  fr, fg, fb, ffulls: byte;
begin
  // Parameter auslesen
  fBitmap:=PThreadParams(Params)^.Bitmap;
  fdx:=PThreadParams(Params)^.dx;
  fdy:=PThreadParams(Params)^.dy;
  fCenter_x:=PThreadParams(Params)^.Center_x;
  fCenter_y:=PThreadParams(Params)^.Center_y;
  fRange_x:=PThreadParams(Params)^.Range_x;
  fRange_y:=PThreadParams(Params)^.Range_y;
  fMaxIterations:=PThreadParams(Params)^.MaxIterations;
  fMaxValue:=PThreadParams(Params)^.MaxValue;
  fCounter:=PThreadParams(Params)^.Counter;

  // Berechnung [...]

  Result:=0;
end;
Die Berechnung an sich habe ich nicht verändert. Sie hat vorher immer ohne Probleme funktioniert und daher gehe ich vorerst davon aus, dass es an den Parametern liegt.

Ich freue mich über Ratschläge!
Max
"Das Ziel ist im Weg!"
  Mit Zitat antworten Zitat
 


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:28 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz