Autor Beitrag
Mitmischer 1703
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 754
Erhaltene Danke: 19

Win 7, Debian
Delphi Prism, Delphi 7, RAD Studio 2009 Academic, C#, C++, Java, HTML, PHP
BeitragVerfasst: Sa 24.04.10 20:31 
Hi DF!

Ich muss euch wegen der parallel loop-Funktion noch mal ansprechen.

Vielleicht ist der Titel nicht ganz korrekt, aber bei folgender Prozedur:

ausblenden Delphi-Prism-Quelltext
1:
2:
3:
4:
5:
method MainForm.button1_Click(sender: System.Object; e: System.EventArgs);
begin
  for parallel i: Int32 := 0 to 3 do begin
   MessageBox.Show(i.ToString); 
end;
`

Muss ich die Messageboxen in der Reihenfolge 3,2,1,0 wegklicken, ansonsten werden mir lustigste Exceptions geworfen. Warum ist das so? Was genau passiert in dem parallel Block?

_________________
Die Lösung ist nicht siebzehn.
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Chefentwickler
Beiträge: 20313
Erhaltene Danke: 2102

Win 10
C# (VS 2017)
BeitragVerfasst: Sa 24.04.10 21:02 
Wenn ich nur Deinen Code benutze, bekomme ich keine Exceptions, egal in welcher Reihenfolge ich die Dinger wegklicke.

Zur Schleife ist zuerst einmal der Beitrag im Wiki ganz hilfreich. Wichtig sind wohl noch folgende Punkte: Der Code wird nicht im GUI-Thread ausgeführt, Zugriffe auf die GUI müssen daher in Aufrufe von Invoke verpackt werden. Außerdem: Die Reihenfolge, in der die Iterationen ausgeführt werden bzw. fertig werden, ist unbekannt.

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Mitmischer 1703 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 754
Erhaltene Danke: 19

Win 7, Debian
Delphi Prism, Delphi 7, RAD Studio 2009 Academic, C#, C++, Java, HTML, PHP
BeitragVerfasst: Sa 24.04.10 21:08 
user profile iconChristian S. hat folgendes geschrieben Zum zitierten Posting springen:
Wenn ich nur Deinen Code benutze, bekomme ich keine Exceptions, egal in welcher Reihenfolge ich die Dinger wegklicke.


Hmm, das ist natürlich doof...

Wie bekomm ich denn mein VS upgegradet?

user profile iconChristian S. hat folgendes geschrieben Zum zitierten Posting springen:
Zur Schleife ist zuerst einmal der Beitrag im Wiki ganz hilfreich. Wichtig sind wohl noch folgende Punkte: Der Code wird nicht im GUI-Thread ausgeführt, Zugriffe auf die GUI müssen daher in Aufrufe von Invoke verpackt werden. Außerdem: Die Reihenfolge, in der die Iterationen ausgeführt werden bzw. fertig werden, ist unbekannt.


Welches Objekt hat denn diese Methode?

_________________
Die Lösung ist nicht siebzehn.
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Chefentwickler
Beiträge: 20313
Erhaltene Danke: 2102

Win 10
C# (VS 2017)
BeitragVerfasst: Sa 24.04.10 21:13 
user profile iconMitmischer 1703 hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconChristian S. hat folgendes geschrieben Zum zitierten Posting springen:
Wenn ich nur Deinen Code benutze, bekomme ich keine Exceptions, egal in welcher Reihenfolge ich die Dinger wegklicke.


Hmm, das ist natürlich doof...

Ist das denn wirklich Dein Code? Denn in dem Quelltext, den Du hier gepostet hast, steht ein "begin" zu viel drin, was drauf hindeutet, dass Du da irgendwas entfernt hast.

Ansonsten: Welche Exceptions kommen denn?

user profile iconMitmischer 1703 hat folgendes geschrieben Zum zitierten Posting springen:
Wie bekomm ich denn mein VS upgegradet?

Ich glaube nicht, dass das mit Deinem VS oder mit der Prism-Version zusammenhängt. Genauer kann man das aber erst bei Kenntnis der Exception sagen.

user profile iconMitmischer 1703 hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconChristian S. hat folgendes geschrieben Zum zitierten Posting springen:
Zur Schleife ist zuerst einmal der Beitrag im Wiki ganz hilfreich. Wichtig sind wohl noch folgende Punkte: Der Code wird nicht im GUI-Thread ausgeführt, Zugriffe auf die GUI müssen daher in Aufrufe von Invoke verpackt werden. Außerdem: Die Reihenfolge, in der die Iterationen ausgeführt werden bzw. fertig werden, ist unbekannt.


Welches Objekt hat denn diese Methode?
Alles, was von Control abgeleitet ist, IIRC. Normalerweise nimmt man die Invoke-Methode der Form.

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Mitmischer 1703 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 754
Erhaltene Danke: 19

Win 7, Debian
Delphi Prism, Delphi 7, RAD Studio 2009 Academic, C#, C++, Java, HTML, PHP
BeitragVerfasst: Sa 24.04.10 21:22 
user profile iconChristian S. hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconMitmischer 1703 hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconChristian S. hat folgendes geschrieben Zum zitierten Posting springen:
Wenn ich nur Deinen Code benutze, bekomme ich keine Exceptions, egal in welcher Reihenfolge ich die Dinger wegklicke.


Hmm, das ist natürlich doof...

Ist das denn wirklich Dein Code? Denn in dem Quelltext, den Du hier gepostet hast, steht ein "begin" zu viel drin, was drauf hindeutet, dass Du da irgendwas entfernt hast.


Stimmt, ich hab die letzten beiden ends weggelassen :oops:


user profile iconChristian S. hat folgendes geschrieben Zum zitierten Posting springen:
Ansonsten: Welche Exceptions kommen denn?


Ich zähle auf (Exception, Klickreihenfolge): InvalidOperationException (2,0), NotSupportedException (2,1), da steht dann als Fehlerbeschreibung "SignalAndWait in einem STA-Thread wird nicht unterstützt", AggregateException(1,3,0) und einmal kommt Windows 7 mit "...exe funktioniert nicht mehr..."


user profile iconChristian S. hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconMitmischer 1703 hat folgendes geschrieben Zum zitierten Posting springen:
Wie bekomm ich denn mein VS upgegradet?

Ich glaube nicht, dass das mit Deinem VS oder mit der Prism-Version zusammenhängt. Genauer kann man das aber erst bei Kenntnis der Exception sagen.

user profile iconMitmischer 1703 hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconChristian S. hat folgendes geschrieben Zum zitierten Posting springen:
Zur Schleife ist zuerst einmal der Beitrag im Wiki ganz hilfreich. Wichtig sind wohl noch folgende Punkte: Der Code wird nicht im GUI-Thread ausgeführt, Zugriffe auf die GUI müssen daher in Aufrufe von Invoke verpackt werden. Außerdem: Die Reihenfolge, in der die Iterationen ausgeführt werden bzw. fertig werden, ist unbekannt.


Welches Objekt hat denn diese Methode?
Alles, was von Control abgeleitet ist, IIRC. Normalerweise nimmt man die Invoke-Methode der Form.


Ist das Invoke wie das Syncronize in Delphi?

_________________
Die Lösung ist nicht siebzehn.
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Chefentwickler
Beiträge: 20313
Erhaltene Danke: 2102

Win 10
C# (VS 2017)
BeitragVerfasst: Sa 24.04.10 21:52 
Invoke führt den übergebenen Code im Thread des Controls auf, über das Invoke aufgerufen wird (also meistens die Form, entsprechend also der GUI-Thread). Wenn Synchronize sowas macht, dann ist es dasselbe. Das ist bei mir einfach zu lang her mit Delphi :D

Versuch mal, den Aufruf der MessageBoxes in Invoke zu verpacken.

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Mitmischer 1703 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 754
Erhaltene Danke: 19

Win 7, Debian
Delphi Prism, Delphi 7, RAD Studio 2009 Academic, C#, C++, Java, HTML, PHP
BeitragVerfasst: Sa 24.04.10 22:05 
Okay, muss nur grad mein Wissen über delegates auffrischen :les:

_________________
Die Lösung ist nicht siebzehn.
Mitmischer 1703 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 754
Erhaltene Danke: 19

Win 7, Debian
Delphi Prism, Delphi 7, RAD Studio 2009 Academic, C#, C++, Java, HTML, PHP
BeitragVerfasst: Sa 24.04.10 22:14 
Stimmt das so?

ausblenden volle Höhe Delphi-Prism-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
 StringDelegate = public delegate (input : String);
  MainForm = partial class(System.Windows.Forms.Form)
  private
    method MainForm_Load(sender: System.Object; e: System.EventArgs);
    method button1_Click(sender: System.Object; e: System.EventArgs);
  protected
    method Dispose(disposing: Boolean); override;
  public
    constructor;
  end

implementation

{$REGION Construction and Disposition}
constructor MainForm;
begin
  //
  // Required for Windows Form Designer support
  //
  InitializeComponent();

  //
  // TODO: Add any constructor code after InitializeComponent call
  //
end;

method MainForm.Dispose(disposing: Boolean);
begin
  if disposing then begin
    if assigned(components) then
      components.Dispose();

    //
    // TODO: Add custom disposition code here
    //
  end;
  inherited Dispose(disposing);
end;
{$ENDREGION}

method MainForm.MainForm_Load(sender: System.Object; e: System.EventArgs);
begin
  
end;

method MainForm.button1_Click(sender: System.Object; e: System.EventArgs);
begin
  for parallel i: Int32 := 0 to 3 do begin
   Invoke(new StringDelegate(MessageBox.Show(i.ToString)));
  end;
end;

end.


Er will das aber nicht nehmen und wirft mir Variable erforderlich und unsafe benötigt

Kannst ja mal drüberschauen, ich glaub ich bin jetzt zu müde ;)

Bis Morgen!

_________________
Die Lösung ist nicht siebzehn.
Christian S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Chefentwickler
Beiträge: 20313
Erhaltene Danke: 2102

Win 10
C# (VS 2017)
BeitragVerfasst: Sa 24.04.10 22:17 
Was soll das für eine Syntax sein? :gruebel:

Hier wird die Syntax für anonyme Methoden und Delegaten gezeigt: prismwiki.codegear.c...ethods_and_Delegates

Lass Dich von dem Dispatcher-Kram beim Invoke nicht irritieren, das ist für WPF und muss Dich nicht interessieren. Die Syntax für anonomye Methoden / Delegaten ist für Dich wichtig.

_________________
Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
Mitmischer 1703 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 754
Erhaltene Danke: 19

Win 7, Debian
Delphi Prism, Delphi 7, RAD Studio 2009 Academic, C#, C++, Java, HTML, PHP
BeitragVerfasst: Mo 26.04.10 17:22 
ich habe jetzt folgendes:

ausblenden Delphi-Prism-Quelltext
1:
2:
3:
4:
5:
6:
method MainForm.button1_Click(sender: System.Object; e: System.EventArgs);
begin
  for parallel i: Int32 := 0 to 0 do begin
   Invoke(method (nr : Integer); begin MessageBox.Show(nr.ToString) end, I);
  end;
end;


Ich habs mal gedebuggt und er läuft theoretisch auch schön alles durch, alles wunderbar - nur werden die MessageBoxen nicht angezeigt und mein Programm friert ein. Funktioniert der Code bei dir?

Edit:

Das hier geht auch nicht:

ausblenden Delphi-Prism-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
method MainForm.button1_Click(sender: System.Object; e: System.EventArgs);
begin
  for parallel i: Int32 := 0 to 0 do begin
   Invoke(new StringDelegate(@DisplayString));
  end;
end;

method MainForm.DisplayString(input : String);
begin
  MessageBox.Show(input);
end

_________________
Die Lösung ist nicht siebzehn.
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mo 26.04.10 18:12 
Irgendetwas scheint mit deinen MessageBoxen ganz und gar nicht zu stimmen ;) . Kannst du die erzeugte Exe mal anhängen? So langsam würde ich mir das gerne mal selbst anschauen :gruebel: .

_________________
>λ=
Mitmischer 1703 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 754
Erhaltene Danke: 19

Win 7, Debian
Delphi Prism, Delphi 7, RAD Studio 2009 Academic, C#, C++, Java, HTML, PHP
BeitragVerfasst: Mo 26.04.10 18:31 
jap

Oder braucht das Invoke irgendne Klasse? Komischerwiese gibt es Self.Invoke, aber MainForm.Invoke nicht. Hat das was zu bedeuten?

Naja, wie dem auch sei, im Anhang liegt die Exe :D
Einloggen, um Attachments anzusehen!
_________________
Die Lösung ist nicht siebzehn.
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Di 27.04.10 00:46 
Soo, noch einmal ein wenig darüber nachgedacht und zu dem Schluss gekommen: Das funktioniert ganz berechtigt bei dir nicht :think: .

Gehen wir das Drama mal durch:
Der GUI-Thread ruft Parallel.For auf, welches ThreadPool-Threads anfordert und wartet, bis alle beendigt sind. Die Neben-Threads rufen nun Invoke auf, was eine Window Message an den Hauptthread schickt mit der Bitte um Bearbeitung des Delegates und auf das Ergebnis wartet. Dummerweise kann der Haupt-Thread schlecht seine Nachrichtenschleife abarbeiten, da er ja selbst auf das Ende von Parallel.For wartet -> klassischer Deadlock :) .

Bei mir ist das Problem interessanterweise dadurch nicht aufgetreten, dass Parallel (sinnvollerweise) den Task des ersten Schleifendurchlaufs "inline", in diesem Fall also im GUI-Thread, ausführt - Invoke entfällt. Das scheint bei deiner PFX-Version noch nicht der Fall gewesen zu sein.

Das Lösen des Deadlocks ist in diesem Fall recht einfach, denn eigentlich gibt es keinen Grund, dass hier irgendjemand wartet. Den Haupt-Thread interessiert es nicht, wann die Schleife beendet ist, also könntest du sie durch ein Task.Factory.StartNew selbst in einem Workerthread starten, oder du benutzt statt Invoke BeginInvoke, damit die Iterationen gar nicht erst auf die GUI warten.

Je nachdem, wie dein eigentliches Problem aussieht, gibt es sicher auch noch andere Lösungen. Wenn du zum Beispiel gar nicht die Features von Parallel.For wie Rückgabewert, Break/Exit, ... benötigst, gibt es keinen Grund, dafür einen weiteren Worker-Thread in Anspruch zu nehmen. Und wenn du statt BeginInvoke Task.ContinueWith benutzt, musst du dich auch nicht mehr ums Weitergeben der Exceptions kümmern.
ausblenden C#-Quelltext
1:
2:
3:
4:
for (int i = 0; i++; i < 10)
  Task.Factory.StartNew(() => {
    return DoSomethingExpensive();
  }).ContinueWith(ShowInGui, TaskScheduler.FromCurrentSynchronizationContext());


PS: Wenn du nicht auf eine neuere Prism-Version upgraden kannst, lass doch wenigstens for parallel links liegen und benutze dafür die PFX-Version aus Rx durch direkte Aufrufe. Wie du siehst, kann eine gewöhnliche For-Schleife manchmal sogar effizienter sein ;) .

_________________
>λ=