Warteschleife für Programm im Hintergrund

  • VB.NET

Es gibt 15 Antworten in diesem Thema. Der letzte Beitrag () ist von Mangafreak1995.

    Warteschleife für Programm im Hintergrund

    Hallo Community ;)

    ich wollte ein Programm schreiben was die ganze Zeit im Hintergrund läuft : vorerst ohne Form (später als Einstellungsdialog).
    Ich habe es nicht hinbekommen eine Forms-Anwendung zu schreiben, wo keine Form gezeigt wird ohne größere Umstände. Unter C# habe ich es dann geschaft, da ich dort eine Forms-Anwendung mit einer Main-Prozedur schreiben kann. zZ sieht der Code so aus :

    Visual Basic-Quellcode

    1. While _shallRun
    2. Application.DoEvents() ' für die MouseEvents im Notify-Icon
    3. Threading.Tread.Sleep(150) ' um die CPU-Auslastung runterzuschrauben
    4. End While

    Wie kann man diesen Code am besten optimieren ?

    Mangafreak1995 schrieb:

    Ich habe es nicht hinbekommen eine Forms-Anwendung zu schreiben, wo keine Form gezeigt wird ohne größere Umstände. Unter C# habe ich es dann geschaft, da ich dort eine Forms-Anwendung mit einer Main-Prozedur schreiben kann. zZ sieht der Code so aus :

    Sry Mangafreak, aber das was Du bisher schreibst ist für mich nicht verständlich. Warum willst Du keine Form, was soll diese Endlosschleife auf dem GUI-Thread und was bezweckst Du mit dem Ganzen ?

    Wenn Du Dein Problem nicht besser beschreibst, so können wir mal wieder nur raten.

    ... und natürlich kannst Du auch in VB.NET eine Application erst einmal ohne Form nur mit einer Sub Main() starten.
    Klar könnte ich das aber dann kommt eine Konsole und ich wüsste nicht wie ich diese ausblenden kann (deswegen auch das "ohne größere Umstände")

    Also ich habe Sub Main und erstelle dort das NotifyIcon und ich möchte dass das NotifyIcon solange da bleibt bis das Programm sich auch beenden soll. Und damit sich das Programm noch nicht beendet warte ich bis ich den Boolean auf False gesetzt habe. Aber das geht doch sicher schöner, oder nicht ?


    Und entschuldige bitte für die tolle Problembeschreibung ;)

    Mangafreak1995 schrieb:

    Klar könnte ich das aber dann kommt eine Konsole und ich wüsste nicht wie ich diese ausblenden kann (deswegen auch das "ohne größere Umstände")

    Seit wann kommt eine Komnsole wenn Du eine Windows.Forms Anwendung mit einer Sub Main() startest ?

    VB.NET-Quellcode

    1. <System.STAThread()> _
    2. Public Shared Sub Main()
    3. System.Windows.Forms.Application.EnableVisualStyles()
    4. System.Windows.Forms.Application.Run(New Form1)
    5. End Sub 'Main


    Mangafreak1995 schrieb:

    Also ich habe Sub Main und erstelle dort das NotifyIcon und ich möchte dass das NotifyIcon solange da bleibt bis das Programm sich auch beenden soll. Und damit sich das Programm noch nicht beendet warte ich bis ich den Boolean auf False gesetzt habe. Aber das geht doch sicher schöner, oder nicht ?

    Am simpelsten ist es mit einer nicht genutzten Form1 mit Visible=False und deinem Notify-Icon in der Taskleiste. Auf die NotifyIcon Events kannst Du reagieren und ggf. mit Application.Exit die ganze Anwendung verlassen.

    Ist Dir das zu unelegant, dann
    - startest Du Deine Anwendung per Sub Main(() wie oben
    - schmeisst die defaultmässig generierte Form1 raus
    - legst Dir eine abgeleitete ApplicationContext Klasse an, in dessen Constructor Du das Notify Icon anlegst
    - startest per Application.Run(ApplicationContext) die MessageLoop

    Anhaltspunkte findest Du hier ApplicationContext Class

    Mangafreak1995 schrieb:

    Und entschuldige bitte für die tolle Problembeschreibung

    Nein. ;)
    Unter Visual Basic 2008 kann ich keine Forms-Anwendung machen ohne eine Startform auszuwählen, ich kann keine <STAThread>Shared Sub Main ansprechen (Bin ich zu blöd dafür xD)

    Ich habe erst daran gedacht das ganze in zwei Threads aufzuteilen. Zur Zeit arbeite ich mit einer Klasse die von ApplicationBase basiert, aber ich werde mal gucken wie sich das mit einer ApplicationContext-Klasse machen lässt ;)

    Mangafreak1995 schrieb:

    Unter Visual Basic 2008 kann ich keine Forms-Anwendung machen ohne eine Startform auszuwählen, ich kann keine <STAThread>Shared Sub Main ansprechen (Bin ich zu blöd dafür xD)

    Du kannst eine Sub Main() in jeder beliebigen Klasse anlegen , solange sie halt nur Shared ist. Ausserdem musst Du die Checkbox "Anwendungsframework" in den Projekteigenschaften deaktivieren, dann kannst Du auch die Startform auf Sub Main umstellen. Etwas mehr dazu und wobei Dich das Anwendungframework unterstützt, siehe 15.3.2 Das Anwendungsframework.

    Nun sollte das auch bei Dir gehen ;)

    Codebeispiel

    VB.NET-Quellcode

    1. Friend Class appMgr
    2. ' the SUB MAIN
    3. <STAThread()> _
    4. Shared Sub Main()
    5. ' create applicationContext
    6. Dim context As MyApplicationContext = New MyApplicationContext()
    7. ' run applicationContext: it will close through notifyIcon
    8. Application.Run(context)
    9. End Sub
    10. End Class
    11. ' my applicationContext which does all the work instead of a Form
    12. Public Class MyApplicationContext
    13. Inherits ApplicationContext
    14. Public WithEvents notifyIcon As NotifyIcon
    15. Public WithEvents notifyMenu As ContextMenuStrip
    16. Public Sub New()
    17. MyBase.New()
    18. ' Handle the ApplicationExit event to know when the application is exiting.
    19. AddHandler Application.ApplicationExit, AddressOf OnApplicationExit
    20. ' create Icon & Menu
    21. notifyIcon = New NotifyIcon With {.Icon = My.Resources.testIcon, .Text = "myApplication", .Visible = True}
    22. notifyMenu = New ContextMenuStrip
    23. ' configure notifyIcon
    24. notifyIcon.ContextMenuStrip = notifyMenu
    25. ' create contextMenu
    26. Dim mnuLabel As New ToolStripButton With {.Name = "btnExit", .Text = "Exit", .ToolTipText = "Exit the application"}
    27. AddHandler mnuLabel.Click, AddressOf mnuItem_Click
    28. Dim mnuHello As New ToolStripButton With {.Name = "btnHello", .Text = "Hello", .ToolTipText = "Say Hello"}
    29. AddHandler mnuHello.Click, AddressOf mnuItem_Click
    30. notifyMenu.Items.AddRange(New ToolStripItem() {mnuHello, mnuLabel})
    31. End Sub
    32. ' Eventhandler: OnApplicationExit
    33. Private Sub OnApplicationExit(ByVal sender As Object, ByVal e As EventArgs)
    34. ' dispose Icon
    35. notifyIcon.Dispose()
    36. End Sub
    37. Private Sub mnuItem_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles notifyMenu.Click
    38. ' check type
    39. If Not TypeOf (sender) Is ToolStripItem Then Return
    40. Dim item As ToolStripItem = CType(sender, ToolStripItem)
    41. Select Case item.Name
    42. Case "btnHello" : MessageBox.Show("Hello")
    43. Case "btnExit" : Application.Exit()
    44. End Select
    45. End Sub
    46. End Class

    Hmm, wenn ich das Anwendungsframework nicht mit einbeziehe sind doch auch die Visuellen Effekte deaktiviert, oder nicht ?

    Ich habe festgestellt, wenn ich das ganze in C und der WinApi mache, dann ist das irgendwie einfacher zu handlen, da diese Schleife viel einfacher aufgebaut ist und keine MainForm gebraucht wird.

    Quellcode

    1. while(GetMessage(&Msg, NULL, 0, 0) > 0)
    2. {
    3. if(!IsDialogMessage(mainWindow, &Msg))
    4. {
    5. TranslateMessage(&Msg);
    6. DispatchMessage(&Msg);
    7. }
    8. }

    Aber noch habe ich das mit dem ApplicationContext nicht ausprobiert; das versuche ich gerade.


    Edit
    Ok, dein Code funktioniert soweit und das ganze wird auch so umgesetzt ;) danke

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

    Mangafreak1995 schrieb:

    Hmm, wenn ich das Anwendungsframework nicht mit einbeziehe sind doch auch die Visuellen Effekte deaktiviert, oder nicht ?

    Du kannst mit Application.EnableVisualStyles() die Effekte aktivieren.

    Allerdings verstehe ich langsame nicht mehr was Du willst: den ganzen Kram mit ApplicationContext kannst Du Dir ja sparen wenn Du nur eine zwar unnütze, aber unsichtbare Form1 im Hintergrund laufen lässt. Deine "einfache" Schleife in C-Code ist auch nichts anderes als das Application.Run: es hält nur die Message-Pump für ein Main-Window am Leben.

    Was ist daran gross einfacher ???
    Naja, ich fand es halt so, aber ich habe halt am Anfang einen umständlichen Weg eingeschlagen, aber dein Codebeispiel ist auf jeden Fall ein einfacher Weg. Was mich interessiert wie du auf die Lösung gekommen bist ? Hast du gegooglet, wenn ja wonach ? Hattest du das Problem selbst schon einmal ? Das mit dem Style ist mir auch eingefallen xD
    Sub Main kannte ich natürlich auch schon ;) Aber den Weg den du gegangen bist auf den bin ich nicht gekommen, aber danke für den Link genau sowas brauchte ich ;)
    @Kangaroo: es geht nicht darum dass es besser ist weil es auf Englisch ist sondern, dass es explizit um Anwendungen geht die nur auf einem NotifyIcon basieren.
    Klar tat dies dein Codebeispiel, aber der Link verweist auf ein ausführlichen Artikel von den man natürlich gut was lernen kann. Ich erwarte aber nicht dass du hier jetzt ellenlange Artikel postest ;)
    Der Link aus deinen Lesezeichen war schon interessant.