Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   C# Zugriff zwischen zwei Threads (https://www.delphipraxis.net/53207-zugriff-zwischen-zwei-threads.html)

faux 12. Sep 2005 11:45


Zugriff zwischen zwei Threads
 
Hallo!

Da ich mich mit Threads nicht auskenne, habe ich zwei simple Fragen:

Ich habe einen Thread in dem nur eine Schleife läuft.
1. Wie kann ich aus diesem Thread herraus eine Komponente des Formulars (das ja logischerweise in einem anderen Thread - im Hauptthread läuft) aufrufen?

2. Beendet sich der Thread automatisch nach ablauf der Schleife, oder muss ich das selbst machen?

Danke schon mal für jede Antwort
Grüße
Faux

Olli 12. Sep 2005 13:11

Re: Zugriff zwischen zwei Threads
 
Zu 2.: Ja, der Thread beendet sich. Allerdings weiß ich nicht, dazu befragst du am besten die Doku, ob das Thread-Objekt (also der .NET-Wrapper) auch freigegeben wird.

Einen Zugriff sollte man immer synchronisieren. Wei du das in .NET machst, ist mir allerdings unbekannt. Außerdem wäre da noch da Problem, daß die eigentlichen drunterliegenden APIs nicht alle threadsafe sind. Ob es die angebotenen Objekte also sind, ist noch eine andere Frage.

faux 12. Sep 2005 16:51

Re: Zugriff zwischen zwei Threads
 
Danke für die Antwort!

Wie könnte ich ansonsten das folgende Problem lösen:

Ich berechne in einer FOR-Schleife, die in einem eigenständigen Thread läuft, pro Durchlauf einen String. Nach jedem Durchlauf soll dieser String dann in eine Komponente (listView) geschrieben werden.
Auf die Komponente kann ich aber nicht einfach so zugreifen, da diese ja in einem seperaten Thread läuft...

Bin für jeden Vorschlag dankbar.
Grüße
Faux

Olli 12. Sep 2005 17:27

Re: Zugriff zwischen zwei Threads
 
Zitat:

Zitat von faux
Ich berechne in einer FOR-Schleife, die in einem eigenständigen Thread läuft, pro Durchlauf einen String. Nach jedem Durchlauf soll dieser String dann in eine Komponente (listView) geschrieben werden.
Auf die Komponente kann ich aber nicht einfach so zugreifen, da diese ja in einem seperaten Thread läuft...

Richte soetwas wie eine gemeinsame Ablage ein (zum Beispiel über Memory Mapped Files). Dort lagerst du dann den aktuellen String und signalisierst dem Hauptthread, daß etwas zur Abholung bereitliegt. Sobald der Hauptthread fertig ist, löscht er die Ablage und signalisiert, daß er fertig ist. Auf einer der beiden Seiten müßtest du dann einen Warteschlangenmechanismus implementieren.

Speedmaster 12. Sep 2005 17:31

Re: Zugriff zwischen zwei Threads
 
Kann man den Thread eigentlich Pausieren?

Olli 12. Sep 2005 17:43

Re: Zugriff zwischen zwei Threads
 
Sollte gehen, aber was soll das bringen? Im Gegensatz zu Fibers ist das nicht sonderlich gut steuerbar. Am sichersten ist es, wenn sich ein Thread selber schlafenlegt.

Stichwort: Suspend

faux 12. Sep 2005 22:30

Re: Zugriff zwischen zwei Threads
 
Zitat:

Zitat von Olli
Zitat:

Zitat von faux
Ich berechne in einer FOR-Schleife, die in einem eigenständigen Thread läuft, pro Durchlauf einen String. Nach jedem Durchlauf soll dieser String dann in eine Komponente (listView) geschrieben werden.
Auf die Komponente kann ich aber nicht einfach so zugreifen, da diese ja in einem seperaten Thread läuft...

Richte soetwas wie eine gemeinsame Ablage ein (zum Beispiel über Memory Mapped Files). Dort lagerst du dann den aktuellen String und signalisierst dem Hauptthread, daß etwas zur Abholung bereitliegt. Sobald der Hauptthread fertig ist, löscht er die Ablage und signalisiert, daß er fertig ist. Auf einer der beiden Seiten müßtest du dann einen Warteschlangenmechanismus implementieren.

Würde das Programm dadurch nicht extrem an Performance verlieren?

Olli 12. Sep 2005 22:34

Re: Zugriff zwischen zwei Threads
 
Zitat:

Zitat von faux
Würde das Programm dadurch nicht extrem an Performance verlieren?

Wieso sollte es? Ich gehe doch mal davon aus, daß du den zweiten Thread nur laufen läßt, weil die Verarbeitung der Strings besonders zeitaufwendig ist. Wenn dem so ist, dürfte der Overhead durch genanntes Prinzip vernachlässigbar sein.

faux 12. Sep 2005 22:42

Re: Zugriff zwischen zwei Threads
 
Ja, das ist schon richtig so, nur wie würdest du das lösen?
Ich würde eine Globale Variable haben, in die der Thread seinen String schreibt. Der Overhead Nimmt dann den String und macht was damit, dann wird der String wieder gelöscht. Der Thread wartet enzwischen auf das Löschen des Strings und fährt dann fort.
NUR:
Wie weißt der Overhead, dass der String jetzt bereit ist? Dan müsste ich ja erst wieder im Overhead ne Schleife laufen lassen, oder?

Kann sein, dass du das jetzt GANZ anders meinst... ;)
Bitte nen mal kurz ein Bsp, wenn das so ist...

Grüße
Faux

Luckie 12. Sep 2005 22:48

Re: Zugriff zwischen zwei Threads
 
Zitat:

Zitat von faux
Wie weißt der Overhead, dass der String jetzt bereit ist? Dan müsste ich ja erst wieder im Overhead ne Schleife laufen lassen, oder?

Ich glaube, hier gibt es noch ein Problem mit dem Begriff Overhead. ;) Als Overhead bezeichnet man das, was zusätzzlich dazu kommt, ohne zur Lösung des Problemes effektiv beizutragen, also Code, Ressourcen usw. Machen tut ein Overhead gar nichts, außer dass er da ist und speicher verbraucht. ;)

faux 12. Sep 2005 22:50

Re: Zugriff zwischen zwei Threads
 
Ups... ;)
Ich dachte, das ist der "Grundprozess", ich weiß nicht, wie man da sonst sagt... :oops:

Luckie 12. Sep 2005 23:01

Re: Zugriff zwischen zwei Threads
 
Auch Prozess ist der falsche Ausdruck. Ein Prozess ist nur ein Container, der den Adressraum usw. für den (Haupt)Thread bereitstellt, der den eigentlichen Code ausführt. Ein Prozess selber führt nie Code aus. Letztendlich läuft es auf einen Handshake hinaus: Der eine Thread sagt dem anderen immer wann er fertig ist und der andere Thread was machen kann. Es geht also immer hin und her wie beim Ping Pong. Dazu hast du drei Threads: den Hauptthread, der die beiden Threads anstößt und die beiden Workerthreads, die letztendlich die Arbeit machen.

Zum Benachrichtigen kann man dann Events nutzen, die sollte es unter .NET auch noch geben oder zu mindes was vergleichbares.

Speedmaster 12. Sep 2005 23:07

Re: Zugriff zwischen zwei Threads
 
Zitat:

Zitat von Olli
Sollte gehen, aber was soll das bringen? Im Gegensatz zu Fibers ist das nicht sonderlich gut steuerbar. Am sichersten ist es, wenn sich ein Thread selber schlafenlegt.

Stichwort: Suspend

Abgesehen davon ob es was bringt oder nicht, kann ich den Thread dann ohne Probleme von einem anderem wieder starten?

Luckie 12. Sep 2005 23:13

Re: Zugriff zwischen zwei Threads
 
Sollte, zu mindest geht es unter WinAPI.

faux 13. Sep 2005 00:27

Re: Zugriff zwischen zwei Threads
 
Zitat:

Zitat von Speedmaster
Zitat:

Zitat von Olli
Sollte gehen, aber was soll das bringen? Im Gegensatz zu Fibers ist das nicht sonderlich gut steuerbar. Am sichersten ist es, wenn sich ein Thread selber schlafenlegt.

Stichwort: Suspend

Abgesehen davon ob es was bringt oder nicht, kann ich den Thread dann ohne Probleme von einem anderem wieder starten?

Ja, ganz einfach mit Resume().

Robert_G 13. Sep 2005 02:28

Re: Zugriff zwischen zwei Threads
 
Du kannst von ThreadX ein Control in seinem Thread ansprechen in dem du einen Delegate an seine Invoke methode schickst.
Um thread safety zu wahren gibt es die Monitor klasse (siehe SDK Doku) oder critical sections:
Code:
lock(someObject)
{
  Statement(someObject);
  someObject.DoSomething();
}
Im allgemein kannst du auch statische Properties als thread safe ansehen solange du in den Accessors nix machst, dass nicht thread safe ist.

faux 16. Sep 2005 19:50

Re: Zugriff zwischen zwei Threads
 
Wenn ich DAS mach:

Code:
lock(typeof(Form1))
{
  Form1.textBox1.Text = Irgendwas;
}
Ist das 1. Zulässig 2. Schön (also gibts ne bessere Möglichkeit) 3. die Form noch Benutzbar, wärend der Thread läuft?

Niko 16. Sep 2005 21:34

Re: Zugriff zwischen zwei Threads
 
Hi,

zulässig ist es, die Form ist auch weiter benutzbar, allerdings ist es so nicht dazu geeignet, um auf ein Control zuzugreifen.

Ein Zugriff auf ein Control muss immer aus dem Thread erfolgen, der das Control angelegt hat, also (so gut wie immer) aus dem Hauptthread der Anwendung. Das kannst du, wie Robert schon geschrieben hat, erreichen, in dem du die Methode die auf das Control zugreift über Invoke aufrufst.

Beispiel:
Code:
public class MyThread
{
   
  public delegate void UpdateDelegate(string s);
   
  public TextBox StatusTB;

  void Update(string s)
  {
    StatusTB.Text = s;
  }

  void Execute() // Thread-Routine
  {
    // ...
    StatusTB.Invoke(new UpdateDelegate(Update), new object[] {"foo"});
    // ...
  }

  // ...
}
Das Problem dabei ist, dass der Invoke-Aufruf so lange nicht zurückkehrt bis die übergebene Methode im Hauptthread ausgeführt worden ist und der Thread somit auch nicht weiterarbeiten kann. Sollte das stören, musst du die Daten in einen Zwischenpuffer schreiben (Array oder ähnliches) den Zugriff darauf synchronisieren (manche Collections gibt's schon als Thread-sichere Variante) und dir eine Möglichkeit überlegen, wie du dem Hauptthread mitteilst, dass neue Daten im Puffer sind.

Zu lock:
Das kannst du verwenden, wenn du auf Felder aus verschiedenen Threads heraus zugreifen willst, und verhindern möchtest, dass sie sich dabei in die Quere kommen.

Beispiel:
Code:
public class GemeinsameDaten
{
  private object dat;

  public object Datum
  {
    set
    {
      lock(this)
      {
        dat = value;
      }
    }
    get
    {
      object d;
      lock(this)
      {
        d = dat;
      }
      return d;
    }
}
Wenn jetzt einer der Threads zum Beispiel set Datum ausführt, wird bei Lock(this) geprüft, ob bereits ein anderer Thread ein lock auf das Objekt ausgeführt hat. Ist das der Fall, dann wartet der neue Thread, bis der andere Thread den kritischen Abschnitt verlassen hat und fährt erst dann fort.

LarsMiddendorf 21. Sep 2005 00:06

Re: Zugriff zwischen zwei Threads
 
Für asynchrone Aufrufe zwischen den Threads gibt es noch BeginInvoke anstelle des einfachen Invoke.


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:25 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz