![]() |
AW: Synchronize mit Argumenten
@Sir Rufo
ich war schon vorher Deiner Meinung, meine Thread-Templates sind auch so aufgebaut. Mir ging es nur darum festzustellen dass es wohl jedes mal abzuwägen gilt welche der Varianten (Queue/Synchronize) für den Anwendungsfall gerade sinnvoll ist. Zitat:
BTW leicht offtopic, wie handhabst Du Syncs zwischen Threads und SubThreads (oder nebenläufigen Threads), also ohne Umweg über den Anwendungsthread? |
AW: Synchronize mit Argumenten
Wieso gehen beim Queue Werte verloren? Klar, wenn man es falsch macht ja, aber wenn ich das Auto nicht richtig beherrsche fahre ich evtl. auch gegen den Baum. :mrgreen:
Also am besten richtig machen ;) Bei meinen Queues gehen keine Werte verloren. (und seit der anonymen Methoden geht halt auch das Queue ohne eigene Warteschlange) Wichtig ist nur am Ende des Threads ein Synchronize zu machen, damit auch wirklich alle Queue-Einträge im Hauptthread verarbeitet wurden. Ansonsten kann es eben halt passieren, dass der Thread (FreeOnTerminate) sich einfach so auflöst und alle bis dahin nicht abgearbeitete Queue-Einträge aus selbigen Thread gehen sang und klanglos mit unter. Zwischen den Threads (auch Hauptthread direkt zum Thread) geht das bei mir immer über eine CS. Manchmal halt auch eine separate CS für den reinen Austausch dieser Daten, wenn es vom Ablauf geschickter ist und dadurch performanter wird. ADD Daten von Thread zu Thread über den Hauptthread auszutauschen halte ich nicht für sinnvoll. Der Hauptthread ist für den User und wird von dem quasi kontrolliert. Wenn der also Samba auf der Tastatur und Maus tanzt, dann könnte er damit auch die Threads beeinflussen. Bei mir darf der das (wenn es nicht meine Maus/Tastatur ist) ;) |
AW: Synchronize mit Argumenten
Wenn man zusammen mit dem Prozedurzeiger auch noch die Parameter mit in dem Queue ablegt, dann gäbt es diesbezüglich auch keine Probleme.
Bzw., man eh nur die selbe Funktion aufrugt, dann reichen auch nur die Werte im Queue, wenn nichts verlorengehen soll. |
AW: Synchronize mit Argumenten
Zitat:
|
AW: Synchronize mit Argumenten
Ich steh immer noch auf dem Schlauch. Habe den Zugriff mit eine CS geschützt.
In dieser CS übertrage ich meine Daten an eine TQueue (Das erste mal dass ich mit Generics gearbeitet habe :stupid:) damit die Blockierung auf ein zeitliches Minimum begrenzt bleibt. Allerdings blockiert das Abarbeiten der Queue die Funktion und es gehen immer noch Werte 'verloren'.
Delphi-Quellcode:
type
TValueQueue = TQueue<Integer>; TForm1 = class(TForm) Memo1: TMemo; Button1: TButton; procedure Button1Click(Sender: TObject); private FMyThread: TMyThread; FValueQueue: TValueQueue; procedure progress(value: Integer); public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin Memo1.Clear; FValueQueue := TValueQueue.Create; FMyThread := TMyThread.Create(true); FMyThread.Progress := progress; FMyThread.Resume; end; procedure TForm1.progress(value: Integer); begin FMyThread.SyncCS.Enter; FValueQueue.Enqueue(value); FMyThread.SyncCS.Leave; while FValueQueue.Count > 0 do begin Memo1.Lines.Add('Value: ' + IntToStr(FValueQueue.Dequeue)); sleep(500); end; end;
Delphi-Quellcode:
Wie mache ich es richtig(er)?
type
TProgress = procedure(Value: integer) of object; type TMyThread = class(TThread) private FValue: Integer; FProgress: TProgress; FSyncCS: TCriticalSection; procedure SyncProgress; protected procedure Execute; override; public property Progress: TProgress write FProgress; property SyncCS: TCriticalSection read FSyncCS; end; implementation uses Windows, SysUtils; { TMyThread } procedure TMyThread.Execute; var i: Integer; begin FSyncCS := TCriticalSection.Create; for i := 1 to 10 do begin FSyncCS.Enter; FValue := i; FSyncCS.Leave; Queue(SyncProgress); sleep(200); end; //if assigned(FSyncCS) then // FreeAndNil(FSyncCS); end; procedure TMyThread.SyncProgress; begin FProgress(FValue); end; |
AW: Synchronize mit Argumenten
!!! OFF TOPIC !!!
Ist ja echt frustrierend :evil: RAD heißt doch Rapid Application Development. Und es heißt doch immer mit Delphi geht alles immer so einfach im Gegensatz zu cpp. Ich habe ein Embedded Projekt mit Qt geschrieben und dachte mir ich versuche jetzt mal ob ich bei Qt auch dieses Problem habe.... Und siehe da, alles ganz einfach. Keine zusätzlichen privaten Felder in denen die zu übergebenden Werte stehen, keine zusätzlichen CS, keine zusätzlichen Methoden, keine Generic Queue oder was weiß ich für Tricksereien und im Gegensatz zu meiner Lösung bei Delphi funktioniert diese Qt Lösung (auf Anhieb nach 10 min) :-(
Code:
class MainWindow : public QMainWindow
{ Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private slots: void on_pushButton_clicked(); void onProgress(qint32); private: Ui::MainWindow *ui; }; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButton_clicked() { MyThread *myThread; myThread = new MyThread(this); connect(myThread, SIGNAL(progress(qint32)), this, SLOT(onProgress(qint32))); myThread->start(); } void MainWindow::onProgress(qint32 value) { ui->plainTextEdit->appendHtml("Value: " + QString::number(value)); Sleep(500); qDebug() << QThread::currentThreadId() << "MainWindow::onProgress - Value:" << QString::number(value); }
Code:
class MyThread : public QThread
{ Q_OBJECT public: explicit MyThread(QObject *parent = 0); signals: void progress(qint32 value); public slots: protected: void run(); }; #include "MyThread.h" #include <windows.h> #include <QDebug> MyThread::MyThread(QObject *parent) : QThread(parent) { } void MyThread::run() { for(qint32 i = 1; i <= 10; i++) { emit progress(i); Sleep(200); qDebug() << QThread::currentThreadId() << "MyThread::run() - Value:" << QString::number(i); } qDebug() << QThread::currentThreadId() << "Fertig"; } Zitat:
Und wie mache ich es jetzt richtig in Delphi (siehe #25)? |
AW: Synchronize mit Argumenten
Du übergibst da aber den Wert direkt an den Thread, bzw du gibst jedem Thread eine Kopie, so daß alle Threads ihre eigenen Werte haben.
In diesen Delphibeispielen nutzt du eine externe Variable für alle Threads. > Äpfel und Birnen |
AW: Synchronize mit Argumenten
@himitsu
und wie übergebe ich Delphi eine Kopie per Queue? |
AW: Synchronize mit Argumenten
Sir Rufo hat ja bereits auf den
![]() Allerdings muss man dann aufpassen (habe ich am Ende des Artikels auch drauf hingewiesen), daß der Thread sich nicht bereits beendet bevor die Queues alle abgearbeitet wurden. Ansonsten gehen die letzten Einträge nämlich verloren (gilt aber für alle Implementationen, die Queue benutzen). Der Vorteil der Anonymen Methode ist einfach, daß man sich um die Kapselung des Parameters keine Gedanken mehr machen muss - das erledigt der Compiler. Das ganze Brimborium mit der TValueQueue ist damit völlig überflüssig. Ach ja: Sollte jemand Probleme haben, den Artikel zu vestehen, da er auf Englisch verfasst ist, könnte ich mich vielleicht dazu durchringen, eine Deutsche Fassung hier an geeigneter Stelle (wo?) bereitzustellen. |
AW: Synchronize mit Argumenten
Also ich bekomme es mit queue nicht hin. :(
Wie muss mein Code von #16 oder #26 abgeändert werden damit das funktioniert? Könnte den korrekten code jemand evtl. posten? Wäre sehr dankbar! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:48 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