none
Kommunikation einzelner Jobs Miteinander RRS feed

  • Frage

  • Hallo,

     

    ich würde gerne mit dem Microsoft WPK Module eine hübsche Oberfläche bauen und diese dann mit der powerShell anzeigen.

    Z.B. New-ListView

     

    die Daten dazu würde ich gerne in einem Modell halten und den ListView in einem separaten Job starten.

     

    New-ListView ... -AsJob

     

    In meinem Hauptscript würde ich nun gerne den Inhalt des Modell's meiner ListView ändern.

    Leider weis ich aber nicht, wie ich den Inhalt von Variablen im Job vom Job Startenden Script ändern kann.

    Gibt es da einen Weg?

     

    Vielen Dank

     

    Jochen

    Montag, 7. Februar 2011 12:39

Antworten

  • Hallo,

    die ultimative Lösung für dieses Problem ist folgendes Beispiel:

    Import-Module WPK
    
    $job = New-Label "Hello World" -Name TextLabel -AsJob
    
    Update-WPFJob -Job $job { 
      $label = Get-ChildControl -tree $window "TextLabel" 
      $label.Content = "New Hello World text"
    }
    
    $job | Update-WPFJob { $window.Close() }
    
    

    damit kann mit den WPK Mechanismen mit dem GUI Thread kommuniziert werden.

     

    Grüße

     

    Jochen

    • Als Antwort markiert Jochen Axt Dienstag, 8. März 2011 17:32
    Dienstag, 8. März 2011 17:32

Alle Antworten

  • Bei einem einmal gestarteten Hintergrundjob kannst du keine Änderungen mehr vornehmen. Du kannst ihn abbrechen, seinen Status und sein Ergebnis abfragen, das wars (_about_Jobs ) .

    Du kannst natürlich innerhalb des Jobs Events abfragen oder eine vom ersten Script geänderte (globale) Variable oder Datei auslesen und damit innerhalb des Jobs Änderungen bewirken.

    Es ist aber ein eher unübliches Vorgehen, einen Teil der GUI in einen Hintergrundjob auszulagern. :) Was willst du denn damit erreichen?

    Grüße, Denniver

    Dienstag, 8. Februar 2011 02:35
    Moderator
  • Hallo Denniver

     

    wie kann ich denn innerhalb eines Jobs auf globale Variablen zugreifen?

    Das wäre ja schon die Lösung, nur bekomme ich das eben nicht hin.

     

    Ich stelle mir so was vor, wobei ich in meinem Hauptscript das masterDataModell beschreibe und im Job dann die Daten anzeige, nicht wie hier mit $dataModell arbeite, sondern wirklich mit $masterDataModell:

    Import-Module WPK

    $global:masterDataModell = @(Get-Date)

    New-ListView -Width 350 -Height 350 -DataBinding @{
        ItemsSource = New-Binding -IsAsync -UpdateSourceTrigger PropertyChanged -Path Output
    } -View {
        New-GridView -AllowsColumnReorder -Columns {
            New-GridViewColumn "Hour"
            New-GridViewColumn "Minute"
            New-GridViewColumn "Second"
        }
    } -DataContext {
        Get-PowerShellDataSource -Script {
            $dataModell += @(Get-Date)
            $dataModell
        }
    }  -On_Loaded {
        Register-PowerShellCommand -Run -In "0:0:02" -ScriptBlock {
            $window.Content.DataContext.Script = $window.Content.DataContext.Script
        }
    } -AsJob

    $masterDataModell += @(Get-Date)
    Sleep -Seconds 2
    $masterDataModell += @(Get-Date)
    Sleep -Seconds 2
    $masterDataModell += @(Get-Date)

    Dienstag, 8. Februar 2011 17:29
  • Mhm ich würde das so nicht machen. Selbst wenn wir einen Weg finden das umzusetzen hättest du das Problem, das script 2 (bzw. der JOB-scriptblock) nicht weiss wann script 1 die Variable ändert. Du könntest natürlich immer wieder abfragen. Aber stell dir vor, Script 1 ändert die Variable während Script 2 gerade mitten in einer Berechnung mit dieser Variable ist. Das Ergebnis wäre unbrauchbar.

    Wenn du unbedingt zwei verschiedene prozesse nutzen willst, wäre IMHO der bessere Weg in Script 1 die Daten in eine Textdatei zu schreiben.

    In script2 kannst du dann ein SystemFileWatcher-Objekt benutzen, das ein Event auslöst sobald eine Änderung der Datei erfolgt ist, und dann die Daten ausliest und verarbeitet.

    Aber nochmal, es gibt keinen wirklich sinnvollen Grund eine GUI in einem Backgroundjob zu starten.  Jobs sind -eher umgekehrt- dafür da, das man z.b. länger dauernde Berechungen auslagern kann, damit diese nicht das "Hauptscript" blockieren. Wenn überhaupt, könnte es also eher sinnvoll sein die Berechnung der Daten die das Listview anzeigen soll in einen Job auszulagern , damit währendessen das Listview nicht blockiert wird.

    Grüße, Denniver

     

     

    Mittwoch, 9. Februar 2011 15:35
    Moderator
  • Hallo Denniver,

     

    das mit dem File wollte ich vermeiden.

     

    Die Umkehrung das ist eine gute Idee. Nur hab ich dann ja wieder dasselbe Problem.

    Wie Kommuniziert dann der Worker Task mit dem GUI Task? Auch wieder über eine Datei oder gibt es da eine andere Möglichkeit?

     

    Grüße

     

    Jochen

    Donnerstag, 10. Februar 2011 08:11
  • Lieber Jochen, :) tu mir doch bitte den Gefallen und erklär mir mal warum du das überhaupt machen willst.

    Ich denke nämlich das dir möglichweise noch nicht (vielleicht täusche ich mich aber auch) bewusst ist, wie GUIs funktionieren. Das Prinzip ist nämlich dieses: wenn eine GUI, sagen wir in diesem Fall mit einem Liestviewobjekt einmal defniert ist, sitzt die GUI nur da und wartet auf sogenannte events, also das irgend etwas passiert, zb. ein Button geklickt wird.
    Ein Backgroundjob macht eigentlich aber nur dann Sinn, wenn man -während irgendeine langwierige Berechnung ausgeführt wird- etwas anderes im Script machen will. Da die GUI aber eh sonst nichts zu tun hat kann man das alles wunderbar im gleichen Script erledigen.

    Aber wie gesagt, vielleicht irre ich mich und du hast das bedacht und trotzdem einen wichtigen Grund die beiden Dinge zu trennen...

    Donnerstag, 10. Februar 2011 13:05
    Moderator
  • Hallo Denniver,

     

    Du hast da ja recht. Die GUI hat sonst nichts zu tun. Leider ist mir aber überhaupt nicht klar, wie ich das mit WPK machen soll.

    Ich hab da ja mein WPF Control und mach da -Show. Dann bleibt eben das Script da hängen und wartet auf Interaktion. Deshalb brauch ich eben den Job.

    Mittlerweile ist mir aber klar geworden wie es gehen kann.

    Durch die Umkehrung dass das GUI Script den Worker Thread startet, kann ich im GUI Script pollend mit Receive-Job die Ausgabe Objekte des Worker Jobs abholen und im GUI anzeigen.

     

    Vielen Dank für Deine Unterstützung

     

    Jochen

    Montag, 14. Februar 2011 07:57
  • Ich hab da ja mein WPF Control und mach da -Show. Dann bleibt eben das Script da hängen und wartet auf Interaktion. Deshalb brauch ich eben den Job.

    Hallo Jochen,

    nicht zwangsläufig. Du kannst z.b die Berechnung deiner Daten (die ins Listview sollen) in einer Funktion definieren. Dann kannst du Events definieren:

    - da es ja sinnvoll ist wenn die GUI gleich mit Daten angezeigt wird, gibt es z.b. das Event OnFormLoad, wenn du hier den ersten Aufruf der Datenfunktion definierst wird das Listview beim ersten erscheinen gefüllt.

    - desweiteren ist eine GUI ja in der Regel für Interaktion gedacht, also wäre der nächste Schritt z.b. ein Button der die Daten neu lädt, ändert etc. mit dem du wieder deine Datenfunktion verknüpfen kannst. Hängt konkret natürlich davon ab worum es bei deinem Script geht.

    - Aber auch ohne Interaktion, kannst du die Daten immer wieder aktualisieren, z.b. mit einem Timer-Objekt. Hierbei definierst du ein Zeitintervall (zb. 30 sec) in dem eine Funktion immer wieder aufgerufen wird. Das kann die Datenfunktion sein, kann aber auch eine andere Funktion sein, die z.b. eine Datei oder Variable checkt und je nach Ergebnis dann die Datenfunktion aufruft.

    Grundsätzlich, so als Tipp, ist WPK zwar prima um einfach nette GUIs zu erstellen, deckt aber leider nicht alle Möglichkeiten ab. Sinnvoller finde ich es, sich erstmal mit klassischen Windows-Forms zu beschäftigen, da man hier lernt wie das ganze prinzipell funktioniert und was alles geht. Ausserdem gibt es schöne WYSIWYG-Editoren dafür, wie Sapiens kostenlose version von PrimalForms.

    Grüße, Denniver

    Ürigens: wenn du einen Beitrag als hilfreich empfindest, makier ihn doch bitte links als "Hilfreich" oder unten als "Antwort".

    Montag, 14. Februar 2011 10:31
    Moderator
  • Hallo,

    die ultimative Lösung für dieses Problem ist folgendes Beispiel:

    Import-Module WPK
    
    $job = New-Label "Hello World" -Name TextLabel -AsJob
    
    Update-WPFJob -Job $job { 
      $label = Get-ChildControl -tree $window "TextLabel" 
      $label.Content = "New Hello World text"
    }
    
    $job | Update-WPFJob { $window.Close() }
    
    

    damit kann mit den WPK Mechanismen mit dem GUI Thread kommuniziert werden.

     

    Grüße

     

    Jochen

    • Als Antwort markiert Jochen Axt Dienstag, 8. März 2011 17:32
    Dienstag, 8. März 2011 17:32