Benutzerdialog im Hintergrund

CopWorker

Erfahrenes Mitglied
Hallo zusammen,

mal wieder ´ne große Herausforderung.

Ich habe ein C# Programm geschrieben der als Hintergrundprozess laufen soll.
Ein Benutzerdialog soll bei Bedarf geöffnet werden um verschiedene Einstellungen zu ändern.
Der Hintergrundprozess startet im Modul "Program.cs"
C#:
static class Program
    {
        #region Instanzen...
        private static OrderManager clOrderMan = new OrderManager();
        #endregion



        /// <summary>
        /// Der Haupteinstiegspunkt für die Anwendung.
        /// </summary>
        [STAThread]
        static void Main()
        {
            clOrderMan.InitOrderManager(); //Hintergrundprozess initialisieren
            clOrderMan.CreateOrderManControl(); //Benutzerdialog einrichten
            clOrderMan.OperatingSession(); //Operating Loop
        }

    }
Der Hintergrundprozess verfügt über eine RPC Schnittstelle worüber dieser von einem anderen Prozess aus gesteuert werden kann.
Z.Bsp. den Benutzerdialog öffnen und schließen.

Die Initialisierung "clOrderMan.InitOrderManger(); wird aufgerufen und durchlaufen.
Der Benutzerdialog "clOrderMan.CreateOrderMancontrol()" wird auch aufgerufen.
C#:
public int CreateOrderManControl()
{
    int iRet = 0;
    bool BShowDlg = false;

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    clOrderManDlg = new OrderManagerDlg(); //Standardkonstruktor wird aufgerufen
    clOrderManDlg.OrderMain = this;
    clOrderManDlg.ShowDlg = BShowDlg;
    Application.Run(clOrderManDlg); //LoadDialog wird aufgerufen

    return iRet;
}

Leider kommt das Programm an der Stelle "clOrderMan.OperatingSession(); nicht an.
Muss der Benutzerdialog in einem eigenen Thread laufen, oder wie geht das am einfachsten.

Bin für jeden Tipp dankbar.
Grüße von CopWorker
 

Spyke

Premium-User
das
C#:
Application.Run(clOrderManDlg); //LoadDialog wird aufgerufen
Application.Run ist ein blockierender Aufruf solange das Fenster nicht geschlossen wird wartet das programm quasi an dieser Stelle.

da du dein Form wenn ich es richtig seh eh als Feld in der Program cs hälst könntest du dieses einfach mit Show aufrufen.
Show ist im Gegensatz zu ShowDialog oder Application.Run keine blockierende Methode.

C#:
clOrderManDlg = new OrderManagerDlg(); //Standardkonstruktor wird aufgerufen
clOrderManDlg.OrderMain = this;
clOrderManDlg.ShowDlg = BShowDlg;
clOrderManDlg.Show();

bei .Net hast du das Glück das das Framework feststellt ob schon eine Nachrichtenschleife gestartet wurde (meist über Application.Run) oder beim Aufruf von Show oder ShowDialog diese gestartet werden muss.


Nachtrag:
hmm könnte sein das sich die Anwendung ev. dennoch beendet da die Main Methode verlassen wurde, alternativ muss dann wohl clOrderMan.OperatingSession() nach oben verschoben werden.
 

CopWorker

Erfahrenes Mitglied
Hallo Spyke,

vielen Dank für deine Unterstützung.
Das mit .Show() geht bedingt.
Der Debugger läuft bis clOrderMan.OperatingSession();
Der Dialog öffnet sich, ist vollständig. Nur ist dieser irgendwie tot. Wartekringel (blau) läuft dauernd.

Schade. Aber irgendwie muss das gehen.

Grüße von CopWorker
 

Spyke

Premium-User
klingt mir so als wenn jetzt OperatingSession() blockiert und diese Methode nicht wirklich asynchron gestartet wurde (hatte verstanden das diese in einem extra Thread/asynchron läuft).

OperatingSession() müsste dann wohl asynchron/in einem extra Thread laufen.

Nachtrag:
falls doch asynchron ist, mal debuggen warum der ladekringel nicht verschwindet
 

CopWorker

Erfahrenes Mitglied
Hi,

die läuft in einem eigenen Thread.
Nix mit while(); So fit bin ich bereits,

C#:
private static Thread OperatingCycle;

public void InitOperatingSession()
{
    OperatingCycle = new Thread(OperatingSession);
    OperatingCycle.Name = "OperatingSessionCycle";
    BOperatingSessionInitRunOk = true; //zur Ausgabe (1x) ins TraceLog File
    OperatingCycle.Start();
}

public void OperatingSession()
{
    while (OperatingCycle.ThreadState == ThreadState.Running)
    {
        if (BOperatingSessionInitRunOk)
        {
            BOperatingSessionInitRunOk = false;
            strInterpreterOperatingSession = GetType().Name + "|" + "OperatingSession()";
            clTrace.GenerateTrace("INFO", strInterpreterOperatingSession, "Thread läuft; Wird nur einmal angezeigt und unterliegt durch den TraceLog keiner fortlaufenden Überwachung");
        }
    }
}

Auszug aus Programs.cs
C#:
/// <summary>
/// Der Haupteinstiegspunkt für die Anwendung.
/// </summary>
[STAThread]
static void Main()
{
    clOrderMan.InitOrderManager();
    clOrderMan.InitOperatingSession();
    clOrderMan.CreateOrderManControl();
}

Der Dialog ist komplett aber mit Wartekringel und tot.
Keine Ahnung, aber davon verdammt viel.
Grüße von CopWorker
 

Spyke

Premium-User
du hast im OperatingSession() eine while schleife, diese müsste eigentlich das Problem sein das dein programm nicht reagiert.
wenn du dort einen Breakpoint mal setzt müsste es eigentlich sein das der debugger in dieser while schleife anhalten müsste

ansosnten während das programm läuft und das fenster hängt mal im VisualStudio die ausführung des Codes pausieren und dann im CallStack mal schauen wo er ev. steht/hängt (ev. auch die anderen Threads mit ihren CallStacks anschauen, aber eigentlich müsst das Problem ja am UI Thread häng)
 

CopWorker

Erfahrenes Mitglied
Hi Spyke,
OperatingSession()
in der Funktion richte ich doch den Thread ein. Die heißt jetzt halt InitOperatingSession();
while (OperatingCycle.ThreadState == ThreadState.Running)
die Schleife brauchst du immer.
Das ist ja grade der Trick dabei. Du hast ´ne Schleife in der Endlosoperationen ausgeführt werden.
Es wird aber nicht blockiert, wird doch vom Core immer, wenn dieser Luft hat, angetriggert.

grüße von CopWorker
 

Spyke

Premium-User
ah sorry ja, habs falsch gelesen gehabt.
Dann bleibt nur die Idee mit dem pausieren des VisualStudio und schauen im CallStack.

Allerings ich glaube das InitOperatingSession hast du neu aufgenommen oder, vorher lief ja direkt OperatingSession (laut Eingangspost).

Du könntest es jetzt nochmal ganz blöd mit
Application.Run(clOrderManDlg);
probieren, nach deiner Umstellung.

Ansosnten bleibt letztendlich wirklich blos im VS pausieren und guggn.
 

CopWorker

Erfahrenes Mitglied
ja, das Einrichten des Threads war anfänglich in der "InitOrderManager();" drin.
Hab´s dann verlegt nach InitOperatingSession();
clOrderMan.InitOrderManager(); clOrderMan.InitOperatingSession();
So, jetzt schau ich mal was im CallStack vor sich geht.

Du könntest es jetzt nochmal ganz blöd mit
Application.Run(clOrderManDlg);
probieren, nach deiner Umstellung.
Das mit "Application.Run(clOrderManDlg);" mach ich auch noch.
Ist nicht blöd, ist die letzte Option einen Dialog ins Leben zu rufen.

Trotzdem vielen Dank.
Das kriegen wir auch noch hin, es gibt keine andere Alternative.

Grüße von CopWorker