AGB  ·  Datenschutz  ·  Impressum  







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

Form in neuem Thread laufen lassen

Ein Thema von Hobbycoder · begonnen am 17. Apr 2017 · letzter Beitrag vom 27. Jul 2017
Antwort Antwort
Seite 1 von 2  1 2      
jus

Registriert seit: 22. Jan 2005
350 Beiträge
 
Delphi 2007 Professional
 
#1

AW: Form in neuem Thread laufen lassen

  Alt 22. Apr 2017, 22:14
Würde denn Interesse bestehen an dem bestehenden Quelltext weiterzuarbeiten? Das ist nicht viel bisher, nur was ich geschildert habe ausprogrammiert und nur Wrapper für einen Button, ein Edit und ein Memo (mehr brauchten wir bisher nicht ). Alle 5 Units zusammen umfassen nur rund 350 Zeilen. Aber es funktioniert so wie es ist.

Es gibt vielleicht die Möglichkeit das ganze unter GPL/LGPL/MPL Triple Lizenz zur Verfügung zu stellen sofern Interesse besteht gemeinsam daran zu arbeiten. Das müsste ich dann bei uns klären.
// EDIT: Die Möglichkeit bestünde, wenn sich noch andere finden, die an dem Projekt mitarbeiten möchten.
@jaenicke:
Danke fürs Angebot, Interesse ja, aber ich weiss nicht, ob es nicht für mich zu steil ist, da mit zu arbeiten.

lg,
jus
  Mit Zitat antworten Zitat
jus

Registriert seit: 22. Jan 2005
350 Beiträge
 
Delphi 2007 Professional
 
#2

AW: Form in neuem Thread laufen lassen

  Alt 23. Apr 2017, 01:58
Hallo,

naja, dann zeige ich mal, was ich bisher habe, viel ist es nicht und ich weiss nicht einmal, ob es überhaupt so richtig ist. Das Projekt besteht aus 2 Units. Habe das gesamte Projekt auch Zip Anhang angehängt.

Habe probeweise auf die Hauptunit folgende Unit1.pas ein Button, Memo und Progressbar draufgeklatscht.
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls,unit2, ComCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    ProgressBar1: TProgressBar;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  DataThread: TDataThread;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  i,j: Integer;
begin
  for I := 0 to 100000 do
  begin
    for j := 0 to 100 do progressBar1.Position:=j;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  DataThread := tDataThread.Create('');
end;

end.
In der folgenden Unit2.pas ist der Thread drin:
Delphi-Quellcode:
unit Unit2;

interface

uses classes, windows, Messages;
type
  TDataThread = class(TThread)
  private
    hdlg: DWORD ;
  protected
    procedure Execute; override;
  public
    constructor Create(const Title:String); reintroduce;
  end;

  function dlgfunc(hwnd: hwnd; umsg: dword; wparam: wparam; lparam: lparam): bool; stdcall;

implementation

{$R main.res} //hier kommt die Vorlage rein

function dlgfunc(hwnd: hwnd; umsg: dword; wparam: wparam; lparam: lparam): bool; stdcall;
begin
  result := true;
  case umsg of
    WM_CLOSE:
      EndDialog(hWnd, 0);
    WM_DESTROY:
      PostQuitMessage(0);
    WM_COMMAND:
      if hiword(wparam) = BN_CLICKED then begin
        case loword(wparam) of
          IDOK:
            begin
              messagebox(hwnd, 'OK Button gedrückt', 'Meldung', 0);
              sendmessage(hwnd, WM_CLOSE, 0, 0);
// PostQuitMessage(0);
            end;
        end;
      end;
  else result := false;
  end;
end;

constructor TDataThread.Create(const Title: String);
begin
  inherited Create(False);
  hdlg := CreateDialog(HInstance, MAKEINTRESOURCE(100), Self.Handle, @DlgFunc);
  ShowWindow(hdlg, SW_SHOW);
end;

procedure TDataThread.Execute;
var
  Msg: TMsg;
begin
  while not terminated do
  begin
    if GetMessage(msg,0,0,0) then
    begin
      if not(IsDialogMessage(hdlg, Msg)) then
      begin
        TranslateMessage(Msg);
        DispatchMessage(Msg);
      end;
    end;
  end;
end;

end.
Das Formular im Thread enhält ein Button und eine Listbox wie folgt in main.rc definiert.
Code:
#define IDC_LIST                       1002

LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL

100 DIALOGEX 6, 18, 264, 200
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_TOOLWINDOW
CAPTION "Fenster-Caption"
FONT 8, "Arial"
BEGIN
    PUSHBUTTON     "OK", IDOK, 61, 65, 140, 14
    LISTBOX        IDC_LIST,7,25,138,106,LBS_NOINTEGRALHEIGHT | 
                    LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP
END
Der TDataThread ladet einfach per Windows API "CreateDialog" das Threaddialogfenster rein und mit "ShowWindow" wird es angezeigt. Wie man in Unit2.pas sieht, habe ich brutal im Thread eine Nachrichtenschleifen eingebaut. Das Threaddialogfenster reagiert sogar, wenn man auf den Button drückt. Ich muß zugeben, dass ich aber nicht weiß, ob es so überhaupt richtig ist, oder komplett auf dem Holzweg bin. Außerdem habe ich festgestellt, dass wenn ich in Unit1.pas auf Button1 klicke, womit der Hauptthread auf meinem Rechner kurzfristig überlastet wird, das Threaddialogfenster in dieser Zeit auch nicht mehr reagiert. Normalerweise sollte doch das Threaddialogfenster unabhängig vom Hauptfenster sein?

Bitte um Unterstützung.

lg,
jus
Angehängte Dateien
Dateityp: zip thread_non_vcl.zip (3,7 KB, 6x aufgerufen)

Geändert von jus (23. Apr 2017 um 02:20 Uhr)
  Mit Zitat antworten Zitat
Fritzew

Registriert seit: 18. Nov 2015
Ort: Kehl
678 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Form in neuem Thread laufen lassen

  Alt 23. Apr 2017, 08:18
Erzeuge alles im execute, das create ist noch im hauptthread, du musst das Window in dem Tread erzeugen in dem es benutzt werden soll.
Fritz Westermann
  Mit Zitat antworten Zitat
Hobbycoder

Registriert seit: 22. Feb 2017
1.002 Beiträge
 
#4

AW: Form in neuem Thread laufen lassen

  Alt 23. Apr 2017, 08:50
Außerdem wäre mein Anspruch, die Forms nicht über Resourcen zu definieren. Damit wäre es dynamischer einsetzbar.
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
772 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Form in neuem Thread laufen lassen

  Alt 23. Apr 2017, 12:19
Hallo HobbyCoder


hier findest du u.a. auch ein Beispiel "Fenster ohne VCL via sep. Thread steuern":

http://stackoverflow.com/questions/1...hout-using-vcl

Du siehst auf dieser Seite auch, wie du Buttons und Co - wie du es gern hättest - zur Laufzeit generierst.

(Ich hatte dir den Link via PM gesendet, du hast ihn wohl übersehen .)
Michael Gasser
  Mit Zitat antworten Zitat
Hobbycoder

Registriert seit: 22. Feb 2017
1.002 Beiträge
 
#6

AW: Form in neuem Thread laufen lassen

  Alt 23. Apr 2017, 12:32
Danke Michael. Hatte ich auch schon gesehen.
Ich werde das auch erst mal so stumpf umsetzen, damit ich die Anforderungen, die ich in meiner Anwendung habe, erst einmal am Laufen habe.

Da ich aber denke, dass ich sowas öfter mal gebrauchen könnte, werde ich mir daraus mal was basteln, was dann leicht wieder verwendbar ist. Wenn das soweit ist, dann werde ich das hier mal posten. Wird aber noch etwas dauern, weil ich leider nicht meine komplette Zeit dafür zur Verfügung stellen kann.
  Mit Zitat antworten Zitat
BrightAngel

Registriert seit: 13. Mär 2007
130 Beiträge
 
#7

AW: Form in neuem Thread laufen lassen

  Alt 23. Apr 2017, 15:00
Hey

Da mich dieses Thema auch schon lange interessiert hat; man könnte sich bei solchen Wrapperklassen auch noch einen weiteren Vorteil sichern: Das Verwenden mehrerer Threads. Das Argument "Synchronisierung" kann man damit tatsächlich auch erschlagen. Windows bietet von Haus aus schon eine Messagequeue für die Nachrichtenbehandlung der Fensterereignisse an (klar, muss ja intern auch irgendwie funktionieren). Das MSDN schreibt dazu:
Zitat:
The function fails if the specified thread does not have a message queue. The system creates a thread's message queue when the thread makes its first call to one of the User or GDI functions. For more information, see the Remarks section.
Man könnte die PostThreadMessage Funktion also benutzen, um kustomisiert auf bestimmte Threadereignisse zu reagieren; oder sehe ich das falsch? Mir schwebt sowas wie ein "Callback" für die WndProc vor. Man registriert eine Callback Funktion auf einen Msg -Code, sodass man dann einfach jedes Mal, wenn man der GUI etwas mitteilen möchte, einfach PostThreadMessage aufruft (oder wenn man das an ein hwnd binden möchte, eben SendMessage /PostMessage ) und die Synchronisierung einfach über Windowsboardmittel durchführt. Wisst ihr was ich meine? Macht das für euch auch Sinn? Ich denke, dass man so zum Beispiel ein Log in einem Memo führen könnte, da die Messages ja immer hübsch einzeln "reinblubbern" - und das egal wie viele Threads im Hintergrund beteiligt sind.

Brighty

P.S. Habe gerade interessehalber diesen Artikel gelesen. Vielleicht interessiert er in diesem Kontext den ein oder anderen. (Falls jemand sprachliche Unterstützung möchte, kann ich btw. gerne übersetzend aktiv werden...)
Do you have the email of god??? --- I have to tell him that I'm happy to be born!

Geändert von BrightAngel (23. Apr 2017 um 15:25 Uhr)
  Mit Zitat antworten Zitat
jus

Registriert seit: 22. Jan 2005
350 Beiträge
 
Delphi 2007 Professional
 
#8

AW: Form in neuem Thread laufen lassen

  Alt 23. Apr 2017, 22:42
Erzeuge alles im execute, das create ist noch im hauptthread, du musst das Window in dem Tread erzeugen in dem es benutzt werden soll.
@Fritzew: Tatsächlich, habe den Createdialog ins Execute verschoben und schon reagiert das Fenster unabhängig von der Auslastung vom Hauptthread. Bin beeindruckt, habe nicht gewußt, dass anscheinend TThread.Create noch im Hauptthread läuft. Vielen Dank für dem essentiellen Hinweis!

Nun zur eigentlichen Frage, ich habe die folgende Messagequeue mit IsDialogMessage, TranslateMessage u. DispatchMessage für den eigenständigen Nonvcl Thread mit:
Delphi-Quellcode:
procedure TDataThread.Execute;
var
  Msg: TMsg;
begin
  hdlg := CreateDialog(HInstance, MAKEINTRESOURCE(100), Self.Handle, @DlgFunc);
  ShowWindow(hdlg, SW_SHOW);
  while not terminated do
  begin
    if GetMessage(msg,0,0,0) then
    begin
      if not(IsDialogMessage(hdlg, Msg)) then
      begin
        TranslateMessage(Msg);
        DispatchMessage(Msg);
      end;
    end;
  end;
end;
überhaupt richtig gemacht, oder würdet ihr es anders lösen? oder anders gefragt, braucht man die überhaupt?

lg,
jus
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#9

AW: Form in neuem Thread laufen lassen

  Alt 24. Apr 2017, 00:09
braucht man die überhaupt?
Ja, die brauchst du in jedem Falle. Aber ist das IsDialogMessage notwendig? Glaube das kannst du weglassen.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#10

AW: Form in neuem Thread laufen lassen

  Alt 24. Apr 2017, 01:44
Die Methode TThread.Create(...) rufts du ja im Hauptthread auf. Wo soll das Fenster also anders "laufen" als im Hauptthread?
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 14:07 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