Einfrieren von Form verhindern

  • VB.NET

Es gibt 41 Antworten in diesem Thema. Der letzte Beitrag () ist von dive26.

    *unnötiges Vollzitat entfernt*

    Also mein longLoad() sollte eigentlich lang lebig sein :D

    VB.NET-Quellcode

    1. Public Sub longLoad()
    2. Using ConsoleProcess As New Process
    3. ConsoleProcess.StartInfo.CreateNoWindow = True
    4. ConsoleProcess.StartInfo.FileName = "cmd.exe"
    5. ConsoleProcess.StartInfo.RedirectStandardOutput = True
    6. ConsoleProcess.StartInfo.RedirectStandardInput = True
    7. ConsoleProcess.StartInfo.UseShellExecute = False
    8. ConsoleProcess.Start()
    9. ConsoleProcess.StandardInput.WriteLine("D:\meine.exe -i " + TextBox1.Text + " " + TextBox2.Text)
    10. 'Label3.Text = ConsoleProcess.StandardOutput.ReadLine()
    11. ConsoleProcess.StandardInput.WriteLine("exit")
    12. ConsoleProcess.WaitForExit()
    13. MsgBox("Tadaaaa... Wirklich Fertig!", MsgBoxStyle.Exclamation) 'Das kommt zu erst und dann das eigentliche "Fertig" wenn man bei der MsgBox auf OK klickt.
    14. End Using
    15. End Sub


    EDIT (WICHTIG): Ok hab es gefunden ... problem sind die Dateien mit leerzeichen als Namen. Da ist was falsch. Ohne Leerzeichen in dem Datei Namen geht es und die Form lässt sich verschieben und alles schön und gut also friert nicht ein und es passiert echt der Konvertierungsvorgang

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Marcus Gräfe“ ()

    PlatinSecurity schrieb:

    Also mein longLoad() sollte eigentlich lang lebig sein
    Seh ich anders. Das geht bei mir durch wie der ICE (ok, schlechtes Beispiel). Dass die gestartete Exe noch läuft hält die Console nicht davon ab sich zu verabschieden und die Sub zu beenden.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @PlatinSecurity

    Ich habe auch heute das erste Mal mit ASYNC gearbeitet und es war eine harte Nuss bis ich verstanden habe wie es funktioniert. War aber für meinen Anwendungfall erforderlich (Email-Abruf im Hintergrund während der User andere Sachen in der Software erledigen kann).

    Jedoch stellt sich die Frage ob Du für Deine Aufgabe überhaupt ASYNC brauchst oder ob das nur unnötiger Balast und Fehlerquellen sind.
    Wenn Du während der Ausführung des Konvertierungsprozesses parallel etwas machen lassen möchtest, dann kommst um ASYNC nicht herum.

    Wenn Du aber eigentlich nur verhindern möchtest, dass während der Konvertierung die Form einfriert und der User ohnehin die Konvertierung abwarten muss, dann verwende einfach application.doevents().

    Beispiel:

    VB.NET-Quellcode

    1. for i as integer = 1 to 1000
    2. Progressbar1.value=i
    3. application.doevents
    4. berechne(i)
    5. next i


    Wenn Du mit ASYNC arbeiten möchtest, dann musst Du verstehen, dass man aus einem als ASYNC aufgerufenen Methode keine Ausgaben in die Form oder andere Controls machen kann. Ich speichere zu übergebende Daten (Statusmeldungen, Zähler) in globalen Variablen DIM GlobalStatusMeldung as STRING und lese diese Variable einfach in einem Timer-Element aus. Das Timer-Element selbst kann dann die Statusmeldung in der Form oder auf einem Control ausgeben. Ich weis zwar nicht ob das die "feine englische Art" ist, aber so funktionierst bei mir.

    Also ich habs so verstanden (Beispiel:)

    VB.NET-Quellcode

    1. Public GlobalStatusBinFertig as boolean=false
    2. Public GlobalStatusMeldung as string=""
    3. Private Sub btn_Emailempfangen_Click(sender As Object, e As EventArgs) Handles btn_Emailempfangen.Click
    4. TimerEmail.interval=200
    5. TimerEmail.enabled=true
    6. NeueEmailsAbrufenAsync()
    7. 'Hier kann sofort mit anderen Tätigkeiten weitergemacht werden.
    8. End Sub
    9. Private Sub TimerEmail_Tick(sender As Object, e As EventArgs) Handles TimerEmail.Tick
    10. Label1.text=GlobalStatusMeldung
    11. if GlobalStatusBinFertig=True then msgbox ("ASYNC Thread ist fertig")
    12. End Sub
    13. Public Async Sub NeueEmailsAbrufenAsync()
    14. Await Task.Run(Sub()
    15. 'hier tun was der Thread tun soll (z.B. die Schleife wie oben)
    16. for i as integer = 1 to 1000
    17. GlobalStatusMeldung ="Bearbeite Datensatz " + i.tostring
    18. berechne(i)
    19. next i
    20. GlobalStatusBinFertig=True
    21. End Sub)
    22. End Sub


    (habe den Code gerade so aus dem FF hier reingeschrieben - sollte aber so in etwa passen)

    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „dive26“ ()

    Zum Thema DoEvents: siehe hiesigen Thread, warum (besser) nicht
    Das mit den globalen Variablen und dem Timer: Da wären wir dann wieder bei BeginInvoke() und Co. als Alternative.
    Falls jemand den Vorschlag EventRaising bringen will: geht nicht, da threadübergreifender Prozess.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Nachdem nun alles zu des TEs Zufriedenheit funktioniert (aber noch nirgends der nun funktionierende Code zu sehen ist) kann ich ja mal anmerken, dass das hier mir überkompliziert erscheint:

    PlatinSecurity schrieb:


    VB.NET-Quellcode

    1. Public Sub longLoad()
    2. Using ConsoleProcess As New Process
    3. ConsoleProcess.StartInfo.CreateNoWindow = True
    4. ConsoleProcess.StartInfo.FileName = "cmd.exe"
    5. ConsoleProcess.StartInfo.RedirectStandardOutput = True
    6. ConsoleProcess.StartInfo.RedirectStandardInput = True
    7. ConsoleProcess.StartInfo.UseShellExecute = False
    8. ConsoleProcess.Start()
    9. ConsoleProcess.StandardInput.WriteLine("D:\meine.exe -i " + TextBox1.Text + " " + TextBox2.Text)
    10. 'Label3.Text = ConsoleProcess.StandardOutput.ReadLine()
    11. ConsoleProcess.StandardInput.WriteLine("exit")
    12. ConsoleProcess.WaitForExit()
    13. MsgBox("Tadaaaa... Wirklich Fertig!", MsgBoxStyle.Exclamation) 'Das kommt zu erst und dann das eigentliche "Fertig" wenn man bei der MsgBox auf OK klickt.
    14. End Using
    15. End Sub
    Da wird die cmd.exe gestartet, und dort wird dann eine Kommandozeile für meine.exe eingegeben.
    Jo, da kannste die cmd doch weglassen, und meine.exe gleich per Process starten. Die Kommandozeile übergibste dabei zB im ProcessStartInfo.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    PlatinSecurity schrieb:

    Keine Ahnung ob das deine Frage beantwortet
    Die Antwort findest Du hier:

    =====
    @dive26 Dein Snippet würde ich nicht in einen Task auslagern, sondern parallelisieren (sofern möglich), wobei alle verfügbaren Prozessoren eingesetzt werden:

    VB.NET-Quellcode

    1. Parallel.For(1, 1001, berechne)
    Die ProgressBar müssste dann per Event inkrementiert und upgedatet werden.
    Application.DoEvents() sind da ein NoGo.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany

    Parallel.For(1, 1001, berechne) Danke, wieder etwas neues gelernt.

    Habs gerade mit einer rechenintensiven Schleife ausprobiert.

    4-Kern Core i5:
    Bei einer normalen For i Schleife wird ein Prozessorkern verwendet (25% Auslastung im Taskmanager)
    Bei einer Parallel.For Schleife werden alle 4 Kerne verwendet (100% Auslastung im Taskmanager).
    Dauer normale For i Schleife ca. 40000 ms.
    Laut Zeitmessung ist die Parallelverarbeitung ca. 25 % schneller.

    8-Kern Core i7:
    Bei einer normalen For i Schleife wird ein Prozessorkern verwendet (16,7% Auslastung im Taskmanager)
    Bei einer Parallel.For Schleife werden alle 8 Kerne verwendet (100% Auslastung im Taskmanager).
    Dauer normale For i Schleife ca. 43000 ms.
    Laut Zeitmessung ist die Parallelverarbeitung ca. 30% schneller.

    Wenn man wirklich zeit- und rechenkritische Aufgaben hat, die über einen längeren Zeitraum berechnen und wo es auf jede Millisekunde ankommt, dann ist das eine super Sache. Ich für mich werde dies aber in meinen "Destop Business Anwendungen" niemals benötigen, da ich nirgends so rechen- oder zeitintensive Aufgaben zu erledigen habe. Für Spiele oder Grafik- und Videosoftware ist das aber klarerweise passend.

    EDIT und NACHTRAG:
    Ich nehme meine Meinung oben zurück.
    Habe gerade mal ausprobiert die 4 Datenbanken, die ich bei Programmstart lade einmal normal und einmal mit Parallel zu laden und die Zeit gemessen. Da ist sehr wohl noch Luft nach oben. Aber bevor ich jetzt meine Software umbaue und mir Fehler einbaue, eine Frage. In der Sub "BefuelleAuftragsListe" befülle ich ein Listview und ein paar Controls mit Informationen. Wenn ich das nun statt "normal" mit Parallel.Invoke
    ausführe, kann das irgend welche ungewollten Ergebnisse bringen?

    VB.NET-Quellcode

    1. Parallel.Invoke(AddressOf BefuelleAuftragsListe)
    2. 'BefuelleAuftragsListe()


    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „dive26“ ()

    ErfinderDesRades schrieb:

    ja, weil auf Controls - auch auf LIstviewItems kann man aus einem Nebenthread nicht zugreifen - kriegst dann eine Exception.


    Leider kann ich Deine Antwort nicht einordnen.

    Ja, geht oder Ja, geht nicht bzw. macht Probleme?

    Ich habe testweise alle Aufrufe von Subs in meiner Anwendung umgestellt und bis jetzt keine negativen Auswirkungen feststellen können. Die mit Parallel.Invoke gestarteten Subs greifen genauso auf alle Controls zu und befüllen das was sie sollen.

    VB.NET-Quellcode

    1. Parallel.Invoke(AddressOf BefuelleAuftragsListe)
    2. 'BefuelleAuftragsListe()

    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    dive26 schrieb:

    Wenn ich das nun statt "normal" mit Parallel.Invoke ausführe, kann das irgend welche ungewollten Ergebnisse bringen?


    ja, es wird ungewollte Ergebnisse bringen

    ErfinderDesRades schrieb:

    weil auf Controls - auch auf LIstviewItems kann man aus einem Nebenthread nicht zugreifen - kriegst dann eine Exception.
    ja, es wird ungewollte Ergebnisse bringen


    Ich hab deshalb gefragt, weil bei mir das Listview auch vom Parallel.Invoke (AddressOf machirgendwasundbefuellelistview) ohne Exceptions befüllt wird.

    Also bei mir funktionierts und Du sagtst es funktioniert nicht. Was nun ;) ?
    Oder meinst Du mit "Nebenthread" nicht Parallel.Invoke (AddressOf machirgendwasundbefuellelistview) sondern das Await Task.Run ?
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „dive26“ ()

    ErfinderDesRades schrieb:


    Aber egal - wenns bei dir doch funzt, dann ist dein Code wohl was besonderes.


    Ist jetzt nicht Dein ernst? Ich möchte niemanden verarschen.
    Ich möchte es wirklich nicht besser wissen. Aber der Code funktioniert so bei mir.

    Hier ein Ausschnitt aus meinem Code:

    VB.NET-Quellcode

    1. ''' <summary>
    2. ''' Drop einer Email in den Posteingang, Postausgang, Archiv und Papierkorb
    3. ''' </summary>
    4. ''' <param name="sender"></param>
    5. ''' <param name="e"></param>
    6. ''' <remarks></remarks>
    7. Private Sub btn_PostfachButton_DragDrop(sender As Object, e As DragEventArgs) Handles btn_PFPosteingang.DragDrop, btn_PFArchiv.DragDrop, btn_PFPapierkorb.DragDrop, btn_PFPostausgang.DragDrop
    8. Dim Listindex As Integer = CInt(e.Data.GetData(DataFormats.Text))
    9. Dim SelbstControl As Button = DirectCast(sender, Button)
    10. If Emails(Listindex).MailOrdner <> SelbstControl.Text Then
    11. Emails(Listindex).MailOrdner = SelbstControl.Text
    12. SchreibeNeueEmailKomplett(Listindex)
    13. Parallel.Invoke(AddressOf LadeAlleEmailsOhneBody)
    14. 'LadeAlleEmailsOhneBody()
    15. Parallel.Invoke(AddressOf ZeigeEmailsInListview)
    16. 'ZeigeEmailsInListview()
    17. End If
    18. End Sub


    LadeAlleEmailsOhneBody lädt die Email-Daten aus der Datenbank (kein Zugriff auf irgend ein Control in dieser Routine)
    ZeigeEmailsInListview gibt die Daten in einem Listview aus (unten ein Teil von ZeigeEmailsInListview)

    VB.NET-Quellcode

    1. Public Sub ZeigeEmailsInListview()
    2. ListView_Emails.BeginUpdate()
    3. Dim ListGesamtBreite As Integer = ListView_Emails.Width - 20
    4. If ListGesamtBreite > 910 Then ListGesamtBreite -= 910
    5. With ListView_Emails
    6. .Clear()
    7. .Columns.Add("Index", 0, HorizontalAlignment.Left)

    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „dive26“ ()

    Arbeitest du Option Strict Off?
    -> Emails(Listindex).MailOrdner <> sender.Text
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    @mrMo

    mrMo schrieb:

    Arbeitest du Option Strict Off?
    -> Emails(Listindex).MailOrdner <> sender.Text


    Ja ;) , aber nicht vom Thema ablenken.
    Habs oben gleich ausgebessert ;-). Danke für den Hinweis.
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „dive26“ ()

    Ich schreibe nicht in VB und habe auch das Parallel.Invoke noch nie benutzt. Aber wo im Paralell.Invoke sind die parallelen Funktionsaufrufe?
    Wenn ich das richtig sehe, dann läuft da nichts paralell, kann auch nicht bei der Logik, weil du ja erst die EMails laden musst bevor du sie in die Listview schreiben kannst.

    Aber wie gesagt, ich habe damit eh noch nie gearbeitet.

    Dksksm schrieb:

    Aber wo im Paralell.Invoke sind die parallelen Funktionsaufrufe?


    Das Parallel bezieht sich darauf, dass die Routinen mit mehreren Prozessorkernen parallel abgearbeitet werden. Man muss zwar noch immer abwarten bis die Routine fertig ist, aber durch die Parallelverarbeitung mit mehreren Prozessorkernen dauert es nicht mehr ganz so lange. Parallel ist nicht Multithreading.
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    dive26 schrieb:

    Parallel ist nicht Multithreading.
    Doch.
    Probierma, aus der parallelisierten Prozedur schreibend auf ein GUI-Control zuzugreigen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Macht er doch in Post#33, z.B. Zeile#20:

    VB.NET-Quellcode

    1. Parallel.Invoke(AddressOf ZeigeEmailsInListview)
    2. '...
    3. Public Sub ZeigeEmailsInListview()
    4. ListView_Emails.BeginUpdate()
    5. '...
    6. With ListView_Emails
    7. .Clear()
    8. .Columns.Add("Index", 0, HorizontalAlignment.Left)
    wobei jetzt noch unklar ist, ob das "Parallellaufen" einer Prozedur wirklich soviel bringt. Parallel ist ja anscheinend dafür gedacht, mehrere Aktionen gleichzeitig laufen zu lassen. Dass es bei @dive26 klappt, liegt m.E. nämlich nur an dem Fakt, dass er als Parameter der Parallel-Invoke-Funktion nur eine Sub-Adresse übergebt. Haut man eine zweite rein, knallt es bei mir die klassische, von vielen hier erwartete threadübergreifende-Prozess-Exception.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    VaporiZed schrieb:

    Macht er doch in Post#33, z.B. Zeile#20:
    Parallel.Invoke(AddressOf ZeigeEmailsInListview)


    Eben nicht, es gibt nur einen Funktionsaufruf, keine Liste fon Funktionsaufrufen, also nix mit Paralell. Und genau da smeinte ich im Post #36.

    VaporiZed schrieb:

    Dass es bei @dive26 klappt, liegt m.E. nämlich nur an dem Fakt, dass er als Parameter der Parallel-Invoke-Funktion nur eine Sub-Adresse übergebt. Haut man eine zweite rein, knallt es bei mir die klassische, von vielen hier erwartete threadübergreifende-Prozess-Exception.


    Nun stimmst mir ja doch zu.