Einfrieren von Form verhindern

  • VB.NET

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

    Einfrieren von Form verhindern

    Guten Morgen zusammen,

    ich möchte gerne verhindern, dass meine Form einfriert wenn Sie ein Process ausführt.

    Ich versuche es mal kurz zu erklären was ich machen möchte...
    Wenn ich eine Datei ausgewählt hab und auf den Start Button klicke, wird diese Datei Konvertiert.
    Problem ist, sobald der Process startet, der dies unternimmt, friert meine Form ein.

    Ich möchte aber das in der Zeit ein Ladebalken (ProgressBar1) anzeigt das sich gerade was tut und
    gleichzeitig soll mit ".StadardOutput.ReadLine()" die Zeile vom versteckten CMD Fenster angezeigt werden in einem Label.
    Damit man halt sieht was gerade passiert.

    Nun ja... Hoffe ihr könnt mir helfen diese Form am leben zu halten ohne das Sie einfriert. ^^
    Auch auf die Gefahr hin, wieder einen auf den Deckel zu bekommen:

    Es währe schöhn, wenn du mal etwas Eigeninitiative an den Tag legen würdest !
    Das Thema ist reichlich im Netz vertreten !
    google.com/search?q=Einfrieren…oe=utf-8&client=firefox-b
    Ein Forum ist nicht dafür da, für irgentwen die "Hausaufgaben" zu machen !

    ErfinderDesRades schrieb:

    Ein typischer Anwendungsfall für Await/Async.
    codeproject.com/Articles/10296…ithout-any-additional-Lin


    Naja, mir ist klar das ich den Sub auf Async stellen kann und muss für dieses Vorgehen.
    Problem ist bei mir nur, Wenn ich z.B.

    Quellcode

    1. Await Task.Run()
    mache kommt immer ein Fehler mit
    "Überladungsauflösung". Ich weiß auch nicht wo ich dieses Task.Run() nutze um die Form nicht Einfrieren zu lassen.

    Und wenn ich

    Quellcode

    1. Await Task.CompletedTask
    nutze, ist der PRocess immer direkt beendet und meine
    MsgBox zeigt "Fertig!" an.

    Edit (Code):

    VB.NET-Quellcode

    1. Private Async Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
    2. If (TextBox1.Text.Equals("") And TextBox2.Text.Equals("")) Then
    3. MsgBox(error_msg1, MsgBoxStyle.Critical)
    4. Else
    5. If (Button3.Text.Equals(button_starter)) Then
    6. Button3.Text = button_stopper
    7. Label7.Text = info_text_progress
    8. Using memStream As New System.IO.MemoryStream(My.Resources.exedatei)
    9. Try
    10. Dim streamFile As New System.IO.FileStream("D:\meine.exe", FileMode.Create)
    11. memStream.WriteTo(streamFile)
    12. streamFile.Close()
    13. streamFile.Dispose()
    14. Catch ex As Exception
    15. MsgBox(ex.ToString, MsgBoxStyle.Critical)
    16. Application.Exit()
    17. End Try
    18. End Using
    19. ProgressBar1.PerformStep()
    20. Using ConsoleProcess As New Process
    21. ConsoleProcess.StartInfo.CreateNoWindow = True
    22. ConsoleProcess.StartInfo.FileName = "cmd.exe"
    23. ConsoleProcess.StartInfo.RedirectStandardOutput = True
    24. ConsoleProcess.StartInfo.RedirectStandardInput = True
    25. ConsoleProcess.StartInfo.UseShellExecute = False
    26. ConsoleProcess.Start()
    27. ConsoleProcess.StandardInput.WriteLine("D:\meine.exe -i " + TextBox1.Text + " " + TextBox2.Text)
    28. Label3.Text = ConsoleProcess.StandardOutput.ReadLine()
    29. ConsoleProcess.StandardInput.WriteLine("exit")
    30. ConsoleProcess.WaitForExit()
    31. End Using
    32. ProgressBar1.Value = 0
    33. 'Label3.Text = ""
    34. 'Label7.Text = ""
    35. Button3.Text = button_starter
    36. MsgBox(finish, MsgBoxStyle.Exclamation)
    37. Else
    38. Button3.Text = button_starter
    39. Label7.Text = abbruch_text
    40. End If
    41. End If
    42. End Sub

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

    PlatinSecurity schrieb:

    Naja, mir ist klar das ich den Sub auf Async stellen kann und muss für dieses Vorgehen

    Das hättest du nicht gleich sagen können ?!

    Ich kann in deinem code, keinen Await Operator endecken, die Vorgehensweise musst du dir nochmal geauer zu Gemühte führen.
    Du solltes alles auch aussagekräftig benamen, sonst blickst du schnell nicht mehr durch.
    Exeptions sollten nur wenn nötig und vorallem gezielt abgefangen werden !
    TryCatch ist ein heißes Eisen
    @PlatinSecurity Mit welchem Framework arbeitest Du?
    Das kannst Du oben im Thread vorgeben.
    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!

    PlatinSecurity schrieb:

    Naja, mir ist klar das ich den Sub auf Async stellen kann und muss für dieses Vorgehen.
    naja, du musst das gegebene Tut auch lesen, und lernen, wie man Async/Await richtig verwendet.
    Mit einfach nur Async iwo vor zuschreiben ist nicht getan.
    Hast du's gelesen?
    Weil da ist ja von einer lang-dauernden Methode die rede, und wie sie aufzurufen ist.
    Das sind also 2 Methoden:
    1) eine, die lang dauert
    2) eine, sie aufruft (eine Button_Click-Methode).

    Solange du diese beiden Dinge nicht getrennt hast, kannste natürlich nix machen.
    Trenne das (also lager das, was lange dauert, aus in eine Methode), und zeig dann den neuen Code.
    Naja man hat mein vorherigen Post anscheinend nicht richtig gelesen.
    Da hätte man gelesen das ich 2 verschiedene Sachen versucht habe und daher noch mal gesagt hab.
    "Ich weiß auch nicht wo ich dieses Task.Run() nutze um die Form nicht Einfrieren zu lassen."

    Und mit Links die ich zwar lese aber nicht verstehe kann ich auch nichts anfangen.

    Wie soll man den mit einem extra dafür angefertigten VB Forum weiter kommen wenn man eine Frage stellt aber
    diese nicht erklärt bekommt, sondern nur "les dir das durch und mach das" ????

    Ich versteh nun mal nicht wie ich das dort anwenden soll und ich will auch kein Profi sein der alles kann sondern
    es sollte einfach nur eine kleine Form für mich Privat hier zu hause den Alltag erleichtern. Aber wenn es nun mal nicht geht
    dann egal.
    Jo, sorry, bitte nicht ärgern.
    Die HIlfe auf VBParadise kommt nur in den seltensten Fällen so schnell wie gewünscht.
    Die Kommunikation ist immer vor allem ein herausarbeiten, was genau der Frager kann, und was genau nicht.
    Gleichzeitig reden Frager oft auch nur ungern darüber, was sie nicht können, daher ist die erste Antwort ein Schuss ins Blaue, der einfach mal davon ausgeht, dass wesentliche Basics gekonnt sind.
    Und dann lieste das Tut - nur den ersten Abschnitt! - und alles wäre paletti gewest, und ich hätte ein "Hilfreich"-Like bekommen.

    Dem war nicht so - stattdessen kommt ein "Ja, das war mir schon klar" - und was folgt zeigt das Gegenteil davon auf.
    Nochmal: Bitte nicht ärgern!! - wenn du es vorziehst, dich zu ärgern, kannst du hier nichts lernen.

    Dann schrieb ich eine wesentlich einfachere Anforderung, damit du der Lösung schrittweise näher kommen kannst:

    ErfinderDesRades schrieb:

    Das sind also 2 Methoden:
    1) eine, die lang dauert
    2) eine, sie aufruft (eine Button_Click-Methode).

    Wie gesagt: bislang ist bei dir alles in einer Methode, nämlich in der Button_Click.
    Erforderlich ist aber, dass das lang-dauernde vom schnellen getrennt wird - du musst das langdauernde in eine eigene Methode auslagern, die dann vom Button_Click aufgerufen wird.
    Also alles, was schnell geht - und das Form nicht blockiert - verbleibt im Button_Click, und was das Form ausbremst, kommt in die Extra-Methode, welche dann vom Button_Click aufgerufen wird.

    Das musst du hinkriegen, ich will dir das erstmal noch nicht fertig servieren.



    Anneres Thema

    PlatinSecurity schrieb:

    will auch kein Profi sein der alles kann
    Ich hab scheints ein anderes Verständnis von Professionalität, und um Professionalität in meinem Sinne kommste beim Programmieren nicht herum:
    Professionell ist, wenn man formuliert, was man nicht kann - so genau wie möglich.
    Wer so vorgeht, der wird in Foren mit effizienter Hilfe totgeworfen, und der lernt auch sehr schnell, Tutorials zu lesen, und von anderen Recherche-Möglichkeiten zu profitieren.

    Das kann einerseits jeder, andererseits kanns keiner - perfekt - das ist das wahre "Learning by Doing", und das hört nie auf.

    Bitte häng dich jetzt nicht an diesem 2. Punkt auf, sondern löse das 1.Thema, oder nähere dich dem wenigstens an, indem du deine Schwierigkeiten damit formulierst.

    RodFromGermany schrieb:

    Mit welchem Framework arbeitest Du?
    Das kannst Du oben im Thread vorgeben.

    @PlatinSecurity Nicht beantwortet, nicht erledigt. ;(
    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!

    ErfinderDesRades schrieb:
    Das sind also 2 Methoden:
    1) eine, die lang dauert
    2) eine, sie aufruft (eine Button_Click-Methode).


    Ok habe es so gemacht, weiß aber nicht ob das überhaupt richtig ist.

    VB.NET-Quellcode

    1. Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
    2. If (TextBox1.Text.Equals("") And TextBox2.Text.Equals("")) Then
    3. MsgBox(error_msg1, MsgBoxStyle.Critical)
    4. Else
    5. If (Button3.Text.Equals(button_starter)) Then
    6. Button3.Text = button_stopper
    7. Label7.Text = info_text_progress
    8. Using memStream As New System.IO.MemoryStream(My.Resources.ffmpeg)
    9. Try
    10. Dim streamFile As New System.IO.FileStream("D:\meine.exe", FileMode.Create)
    11. memStream.WriteTo(streamFile)
    12. streamFile.Close()
    13. streamFile.Dispose()
    14. Catch ex As Exception
    15. MsgBox(ex.ToString, MsgBoxStyle.Critical)
    16. Application.Exit()
    17. End Try
    18. End Using
    19. ProgressBar1.PerformStep()
    20. longLoad()
    21. ProgressBar1.Value = 0
    22. 'Label3.Text = ""
    23. 'Label7.Text = ""
    24. Button3.Text = button_starter
    25. MsgBox(finish, MsgBoxStyle.Exclamation)
    26. Else
    27. Button3.Text = button_starter
    28. Label7.Text = abbruch_text
    29. End If
    30. End If
    31. End Sub
    32. Public Sub longLoad()
    33. Using ConsoleProcess As New Process
    34. ConsoleProcess.StartInfo.CreateNoWindow = True
    35. ConsoleProcess.StartInfo.FileName = "cmd.exe"
    36. ConsoleProcess.StartInfo.RedirectStandardOutput = True
    37. ConsoleProcess.StartInfo.RedirectStandardInput = True
    38. ConsoleProcess.StartInfo.UseShellExecute = False
    39. ConsoleProcess.Start()
    40. ConsoleProcess.StandardInput.WriteLine("D:\meine.exe -i " + TextBox1.Text + " " + TextBox2.Text)
    41. Label3.Text = ConsoleProcess.StandardOutput.ReadLine()
    42. ConsoleProcess.StandardInput.WriteLine("exit")
    43. ConsoleProcess.WaitForExit()
    44. End Using
    45. End Sub


    Muss ich nun bei den Button "Private Async Sub" machen oder bei dem "longLoad()" ?
    Oder ist der Ansatz auch wieder Falsch ?

    EDIT:

    RodFromGermany schrieb:

    RodFromGermany schrieb:

    Mit welchem Framework arbeitest Du?Das kannst Du oben im Thread vorgeben.
    @PlatinSecurity Nicht beantwortet, nicht erledigt.
    Sry ich Arbeite mit Microsoft Visual Studio 2017 - Windows Forms-App (.NET Framework)Keine Ahnung ob das deine Frage beantwortet ?! :o
    Die Prozedur-Markierung Async erfolgt im Button_Click-Prozedurkopf. Im Button_Click-Code selbst an passender Stelle das Await. Ich stell mir das dann meistens so vor:

    VB.NET-Quellcode

    1. Public Async Sub Whatever 'Achtung! Irgendwo wird in dieser Prozedur auf irgendwas mal gewartet*
    2. 'Codeblock 1
    3. Await LangDauerndeAufgabe '= warte darauf, das LangDauerndeAufgabe fertig wird und mache danach weiter mit Codeblock 2
    4. 'Codeblock2
    5. End Sub

    *wobei »warten« fast schon der falsche Ausdruck ist. Eigentlich ist das Programm ja eher ungeduldig und will eben nicht warten, bis die Aufgabe fertig ist, sondern sagt sich: ok, wenn die Aufgabe fertig ist, mach ich da weiter, aber inzwischen mach ich all die anderen Dinge, die so anstehen.

    btw: Gibt's n Grund mit dem VB6-Namespace noch zu arbeiten? Stichwort MsgBox
    und statt sowas hier:

    VB.NET-Quellcode

    1. If VorbedingungenSindNichtGegeben Then
    2. MessageBoxMitWarnhinweis
    3. Else
    4. 'ewig viel Code
    5. End If

    arbeite ich gern eher so, da das für mich übersichtlicher ist:

    VB.NET-Quellcode

    1. If VorbedingungenSindNichtGegeben Then
    2. MessageBoxMitWarnhinweis
    3. Exit Sub
    4. End If
    5. 'ewig viel Code

    Erspart einem das Else und die Einrückung.

    Aber wie Du möchtest.

    ##########

    zum Framework: Menü Projekt -> ganz unten [Dein Projektname]-Eigenschaften -> Reiter Anwendung -> Einstellungscombobox "Zielframework"
    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.

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

    Ok. Danke für die Erklärung.
    Nur mache ich anscheinend ja immer was falsch. Obwohl ihr es ja mir versucht richtig zu erklären.
    Andere die da mehr Ahnung als ich haben, haben es mit Sicherheit jetzt schon verstanden.

    Nur ich frage mich warum mein "longLoad()" ein Fehler ausgibt mit "Der Ausdruck ergibt keinen Wert."

    Was für ein Wert will er den ?
    Warum muss er ein Wert haben ?

    Ich dachte ich kann es einfach "machen" lassen.
    Also dass er im Hintergrund dieses Command ausführt und dann dabei mit ReadLine die Daten in mein Label schreibt.

    Ich hätte wirklich nicht gedacht, dass so eine kleine Idee mein Leben zu vereinfachen dann doch ehr schwer wird.

    EDIT:
    Habe ja auch mal was von einem BackgroundWorker gehört aber ist es hier ein muss den zu nutzen oder ist der in dem Fall nicht so wichtig ?
    Dann auch wie nutzt man Ihn in dieser Situation ?
    Lass mal den BackgroundWorker weg. Wenn man das Async Zeug verstanden hat anzuwenden, isses super easy... lohnt sich also sich damit zu beschäftigen. Hier ein kleines Zuckerle damit du weiter kommst:

    Private Async Sub()
    Await Task.Run(AddressOf DeineMethode)
    End Sub

    "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 schrieb:

    Lass mal den BackgroundWorker weg. Wenn man das Async Zeug verstanden hat anzuwenden, isses super easy... lohnt sich also sich damit zu beschäftigen. Hier ein kleines Zuckerle damit du weiter kommst:

    Private Async Sub()
    Await Task.Run(AddressOf DeineMethode)
    End Sub



    Omg danke... Es sieht echt aktuell gut aus :D
    Jetzt muss ich nur noch bisschen versuchen den "Label3.Text = ConsoleProcess.StandardOutput.ReadLine()"
    Fehler "Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement Label3 erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde." zu beheben..

    Sagt euch natürlich mehr als mir der Fehler.

    Ich versteh es so das dies natürlich nicht in longLoad() stehen darf sondern draußen stehen muss.
    Aber das ist wieder so ne Sache für sich bei einem Anfänger. ^^

    PlatinSecurity schrieb:

    Ich versteh es so das dies natürlich nicht in longLoad() stehen darf sondern draußen stehen muss.

    Ja korrekt. Der Zugriff auf Controls aus einem Separaten Thread ist nicht direkt möglich(per Control.Invoke/Control.BeginInvoke hingegen schon). Für den Anfang, lass das einfach weg.
    "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 schrieb:

    PlatinSecurity schrieb:

    Ich versteh es so das dies natürlich nicht in longLoad() stehen darf sondern draußen stehen muss.

    Ja korrekt. Der Zugriff auf Controls aus einem Separaten Thread ist nicht direkt möglich(per Control.Invoke/Control.BeginInvoke hingegen schon). Für den Anfang, lass das einfach weg.


    Ok wenn ich das erst mal weg lasse mit dem ReadLine() und dem was du sagtest ".Invoke" oder ".BeginnInvoke"

    Wird trotz diesem "Await Task.Run(AddressOf longLoad)" sofort Fertig angezeigt.
    Also macht er ja so wie es aussieht nichts in meiner lonLoad() ??????
    Als Alternative zum Weglassen und auf Deine Frage hin, warum da was zurückgegeben werden muss:

    VB.NET-Quellcode

    1. Private Async Sub DeineAufrufSub()
    2. Label3.Text = Await longLoad
    3. End Sub
    4. Public Async Function longLoad() As Task(Of String)
    5. Dim ResultText As String = Nothing
    6. Using ConsoleProcess As New Process
    7. ConsoleProcess.StartInfo.CreateNoWindow = True
    8. ConsoleProcess.StartInfo.FileName = "cmd.exe"
    9. ConsoleProcess.StartInfo.RedirectStandardOutput = True
    10. ConsoleProcess.StartInfo.RedirectStandardInput = True
    11. ConsoleProcess.StartInfo.UseShellExecute = False
    12. ConsoleProcess.Start()
    13. ConsoleProcess.StandardInput.WriteLine("D:\meine.exe -i " + TextBox1.Text + " " + TextBox2.Text)
    14. ResultText = ConsoleProcess.StandardOutput.ReadLine()
    15. ConsoleProcess.StandardInput.WriteLine("exit")
    16. ConsoleProcess.WaitForExit()
    17. End Using
    18. Return ResultText
    19. End Sub

    Damit Await auch weiß, wann die langatmige Aufgabe fertig ist, muss diese was zurückgeben. Wenn man dann einen Task mit Parameter angibt, erhält man jenen Parametertyp zurück. Ohne Parameter würde es dann z.B. so aussehen:

    VB.NET-Quellcode

    1. Private Async Sub DeineAufrufSub()
    2. Await longLoad
    3. End Sub
    4. Public Async Function longLoad() As Task
    5. End Function

    Allerdings ist das nur dann sinnvoll, wenn dann in der longLoad() mit Await (weiter-)gearbeitet wird. Von daher arbeite mit mrMos Task.Run-Vorschlag. Das sollte (für den Anfang) genügen.

    @PlatinSecurity: Zeig mal bitte den Teil mit der Fertig-MessageBox. Davor müsste ja eine Await-Zeile stehen. Zeig mal bitte diese 2 Zeilen.
    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.

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

    VaporiZed schrieb:

    Als
    @PlatinSecurity: Zeig mal bitte den Teil mit der Fertig-MessageBox. Davor müsste ja eine Await-Zeile stehen. Zeig mal bitte diese 2 Zeilen.


    Ok... Ehm ja ^^

    Also meine letzten Zeilen sehen da so aus:

    VB.NET-Quellcode

    1. ProgressBar1.PerformStep()
    2. Await Task.Run(AddressOf longLoad)
    3. ProgressBar1.Value = 0
    4. 'Label3.Text = ""
    5. 'Label7.Text = ""
    6. Button3.Text = button_starter
    7. MsgBox(finish, MsgBoxStyle.Exclamation)

    Und da macht er halt direkt ende statt die longLoad() zu machen.
    Dabei sollte diese eigentlich was machen.
    Wenn ich folgendes Konstrukt verwende

    VB.NET-Quellcode

    1. Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. Await Task.Run(AddressOf LongLastingWork)
    3. MessageBox.Show("fertig")
    4. End Sub
    5. Public Sub LongLastingWork()
    6. For i = 1 To 1000000000
    7. Next
    8. End Sub

    kommt bei mit die Infobox erst, wenn die For-Loop durch ist. Kann es sein, dass Deine scheinbar langlebige Aufgabe doch nicht so viel Zeit in Anspruch nimmt und der Memory-Copy-Teil eher der Flaschenhals ist? Hau doch mal ne MessageBox ans Ende der LongLoad-Sub, um zu sehen, wann sie wirklich fertig ist.
    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.