Hallo zusammen,
ich habe vor einiger Zeit begonnen, einen Server-Manager zu programmieren, der auf einem Root-Server läuft. Weitere Infor hier: List Of <Class>, vorherige Elemente werden überschrieben
Soweit funktioniert auch (fast) alles.
Als Vorabinfo zu meinem aktuellen Problem noch folgendes:
Der Servermanager kann sowohl lokal über Buttons usw. direkt bedient werden, als auch über ein Web-Interface gesteuert werden. Für die Kommunikation mit dem Web-Interface läuft ein eigener Thread. Es gibt eine Funktion, die die Server updaten soll. Dazu muss ein externes Kommandozeilen-Programm aufgerufen werden, das den Server updatet und sich danach beendet.
Um festzustellen, wann der Updater fertig ist, läuft ein Timer, der zyklisch prüft, ob der Prozess beendet ist (vielleicht nicht die beste Variante, funktioniert aber). Das Update wird über die Funktion
Daher meine Frage: Kann ein Timer standardmäßig nicht threadübergreifend gestartet werden? Wie bekomme ich das hin, dass der Timer auch aus dem anderen Thread heraus gestartet wird (bzw warum wird die Funktion ausgeführt, nur das Starten des Timers nicht?)?
Vielen Dank schon mal im Vorraus!
cya Igel
Form Load:
Timer:
Update-Funktion:
Kommunikation mit dem Web-Interface:
ich habe vor einiger Zeit begonnen, einen Server-Manager zu programmieren, der auf einem Root-Server läuft. Weitere Infor hier: List Of <Class>, vorherige Elemente werden überschrieben
Soweit funktioniert auch (fast) alles.
Als Vorabinfo zu meinem aktuellen Problem noch folgendes:
Der Servermanager kann sowohl lokal über Buttons usw. direkt bedient werden, als auch über ein Web-Interface gesteuert werden. Für die Kommunikation mit dem Web-Interface läuft ein eigener Thread. Es gibt eine Funktion, die die Server updaten soll. Dazu muss ein externes Kommandozeilen-Programm aufgerufen werden, das den Server updatet und sich danach beendet.
Um festzustellen, wann der Updater fertig ist, läuft ein Timer, der zyklisch prüft, ob der Prozess beendet ist (vielleicht nicht die beste Variante, funktioniert aber). Das Update wird über die Funktion
UpdateGameServer(..)
gestartet, die eben den Updater und danach den Timer startet. Diese Funktion wird sowohl lokal über einen Button, als auch über das Web-Interface aufgerufen. Der Updater wird in beiden Fällen gestartet, der Timer allerdings nur, wenn die Funktion lokal über den Button ausgeführt wird.Daher meine Frage: Kann ein Timer standardmäßig nicht threadübergreifend gestartet werden? Wie bekomme ich das hin, dass der Timer auch aus dem anderen Thread heraus gestartet wird (bzw warum wird die Funktion ausgeführt, nur das Starten des Timers nicht?)?
Vielen Dank schon mal im Vorraus!
cya Igel
Form Load:
VB.NET-Quellcode
- Public Class Hauptfenster
- Private Delegate Sub UpdateTextDelegate(RTB As RichTextBox, txt As String)
- Private Sub Hauptfenster_Load(sender As Object, e As EventArgs) Handles MyBase.Load
- Me.Text = "ServerManager - " & "V" & FileVersionInfo.GetVersionInfo(IO.Path.GetFileName(Application.ExecutablePath)).FileVersion.ToString
- If System.Diagnostics.Process.GetProcessesByName("ServerManager").Count > 1 Then
- Dim proc As Process = System.Diagnostics.Process.GetCurrentProcess()
- MessageBox.Show(Me, "Eine Instanz des ServerManagers läuft bereits.", "ServerManager", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
- proc.Kill()
- End If
- CheckForIllegalCrossThreadCalls = False
- LoadServerList()
- TCPServer = New TCPControl("127.0.0.1", 4305)
- AddHandler TCPServer.MessageReceived, AddressOf ValidateRequestAndRespond
- TxtServername.Text = "-- kein Server ausgewählt --"
- If ProgramData.Servers.Count = 0 Then
- ServerBearbeitenToolStripMenuItem.Enabled = False
- ServerLöschenToolStripMenuItem.Enabled = False
- End If
- If ProgramData.Settings.AllowRemoteControl = True Then
- TCPServer.StartServer()
- Else
- TCPServer.StopServer()
- TaReceive.Enabled = False
- End If
- TimGameServerMonitoring.Enabled = True
- TimApplicationRunningCheck.Enabled = True ' UpdateProcessTimer - 5 sec
- .
- .
- .
- End Sub
- .
- .
Timer:
VB.NET-Quellcode
- Private Sub TimApplicationRunningCheck_Tick(sender As Object, e As EventArgs) Handles TimApplicationRunningCheck.Tick ' 5 Sekunden
- Dim updateCount As Integer = 0
- Console.WriteLine("TimApplicationRunningCheck_Tick...")
- For srvIdx As Integer = 0 To ProgramData.Servers.Count - 1
- If Not ProcessIsRunning(ProgramData.Servers(srvIdx).SteamCMDPID) Then
- If ProgramData.Servers(srvIdx).Serverstate = ServerStatus.UpdatingStart Then
- Dim status As Boolean = CBool(StartGameServer(ProgramData.Servers(srvIdx).ID, True))
- If status = True Then
- SetServerControls(ServerStatus.Running, ProgramData.Servers(srvIdx).ID)
- Else
- SetServerControls(ServerStatus.Stopped, ProgramData.Servers(srvIdx).ID)
- End If
- ProgramData.Servers(srvIdx).SteamCMDPID = 0
- ElseIf ProgramData.Servers(srvIdx).Serverstate = ServerStatus.Updating Then
- SetServerControls(ServerStatus.Stopped, ProgramData.Servers(srvIdx).ID)
- ProgramData.Servers(srvIdx).SteamCMDPID = 0
- End If
- Else
- updateCount += 1
- End If
- Next
- If updateCount = 0 Then
- TimApplicationRunningCheck.Enabled = False
- End If
- End Sub
Update-Funktion:
VB.NET-Quellcode
- Function UpdateGameServer(ServerID As Integer, Optional ByVal SilentMode As Boolean = False) As Integer
- Dim procID As Integer = 0
- Dim srvIdx As Integer = ProgramData.GetSrvIdx(ServerID)
- If System.IO.File.Exists(ProgramData.Settings.SteamCmdPath) Then
- Dim procProp As New ProcessStartInfo
- If Not ProcessIsRunning(ProgramData.Servers(srvIdx).SteamCMDPID) Then
- Try
- procProp.FileName = ProgramData.Settings.SteamCmdPath
- procProp.Arguments = "+login anonymous +force_install_dir " & ProgramData.Servers(srvIdx).Path & " +app_update " & ProgramData.Settings.AppID & " validate +quit"
- procProp.WindowStyle = ProcessWindowStyle.Minimized
- procID = Process.Start(procProp).Id
- ProgramData.Servers(srvIdx).SteamCMDPID = procID
- Hauptfenster.TimApplicationRunningCheck.Enabled = True
- ServerLogFiles(srvIdx).Add("SERVER STATUS", "UpdateGameServer(): Server updating")
- Catch ex As Exception
- procID = 0
- If SilentMode = False Then MsgBox("Es ist ein unbekannter Fehler beim Starten von SteamCMD aufgetreten!", vbCritical, "Update-Status")
- ServerLogFiles(srvIdx).Add("SERVER STATUS", "UpdateGameServer(): Unkown error occured!")
- End Try
- Else
- procID = 0
- If SilentMode = False Then MsgBox("Es läuft bereits eine Update-Routine.", vbExclamation, "Update-Status")
- ServerLogFiles(srvIdx).Add("SERVER STATUS", "UpdateGameServer(): Update already running.")
- End If
- Else
- If SilentMode = False Then MsgBox("Das Update konnte nicht gestartet werden, da der angegebene SteamCMD-Pfad nicht korrekt ist." & vbCrLf & vbCrLf & "Bitte Einstellungen überprüfen!", vbExclamation, "Fehler beim Starten des Updates")
- ServerLogFiles(srvIdx).Add("SERVER STATUS", "UpdateGameServer(): Update could not be started - Wrong SteamCMD path.")
- End If
- ServerLogFiles(srvIdx).Save()
- Return procID
- End Function
Kommunikation mit dem Web-Interface:
VB.NET-Quellcode
- ' --------------------------------------------------------------------------------------------------------------------
- ' --------- TCP VERBINDUNG -------------------------------------------------------------------------------------------
- ' --------------------------------------------------------------------------------------------------------------------
- Sub ValidateRequestAndRespond(sender As TCPControl, ByVal request As String)
- If TCPServer.ServerStatus = True Then
- Dim command As String = ""
- Dim parameter As String = ""
- Dim SrvIdx As Integer = -1
- Dim GameServerStatus As Boolean = False
- If request.IndexOf("(") > -1 And request.IndexOf(")") > request.IndexOf("(") Then
- command = request.Substring(0, request.IndexOf("("))
- parameter = request.Substring(request.IndexOf("(") + 1, request.IndexOf(")") - (request.IndexOf("(") + 1))
- Else
- command = request
- parameter = ""
- End If
- Select Case command
- Case "SetServerUpdate"
- SrvIdx = ProgramData.GetSrvIdx(CInt(parameter))
- If IsNumeric(parameter) And SrvIdx > CONST_INVALID Then
- GameServerStatus = CBool(UpdateGameServer(CInt(parameter), True))
- If GameServerStatus = True Then
- SetServerControls(ServerStatus.Updating, CInt(parameter))
- TCPServer.SendToClient("success")
- Else
- TCPServer.SendToClient("failed")
- End If
- UpdateText(TaReceive, request)
- ServerLogFiles(SrvIdx).Add("REMOTE CONTROL", "SetServerUpdate received")
- ServerLogFiles(SrvIdx).Save()
- Else
- TCPServer.SendToClient("wrong ID")
- End If
- ' ...
- Case Else
- 'Me.TaReceive.Text = request
- UpdateText(TaReceive, "WRONG CMD: " & request)
- AppLogFile.Add("REMOTE CONTROL", request & " received (wrong command)")
- AppLogFile.Save()
- TCPServer.SendToClient("wrong command")
- End Select
- End If
- End Sub
- ' UPDATE TEXTBOX
- Private Sub UpdateText(RTB As RichTextBox, txt As String)
- If RTB.InvokeRequired Then
- RTB.Invoke(New UpdateTextDelegate(AddressOf UpdateText), New Object() {RTB, txt})
- Else
- If txt IsNot Nothing Then RTB.AppendText("[" & Format(Now, "dd.MM.yyyy HH:mm:ss") & "] " & txt & vbCrLf)
- RTB.ScrollToCaret()
- End If
- End Sub