myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » GUI: Windows-Forms » Waitform in extra Thread
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Waitform in extra Thread

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
theflyer
myCSharp.de-Mitglied

Dabei seit: 07.05.2007
Beiträge: 15
Entwicklungsumgebung: VS C# 2005
Herkunft: Münster


theflyer ist offline

Waitform in extra Thread

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

[EDIT]Abgeteilt von  MdiFenster mit unterschiedlichen Threads[EDIT]

Habe just so ein ähnliches Problem

Wir haben eine globale Waitform, also so ein "Bitte Warten" Fenster mit einer netten Animation darin.

Leider machen die meisten Progger bei uns das Fenster auf, führen ihre Berechnungen im selben GUI Thread aus, so das die Animation steht und schließen danach das Fenster wieder.

Wäre es aber nicht möglich, die Waitform in einen eigenen Thread zu erzeugen und keinen Parent zuzuweisen, so das es völlig autark ist. Nur die Show/Hide Methoden müßten dann noch über Invoke aufgerufen oder überschrieben werden.

Oder denke ich da falsch enttäuscht ?

Gruss
theflyer
15.05.2008 22:52 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
michlG michlG ist männlich
myCSharp.de-Poweruser/ Experte

avatar-2909.png


Dabei seit: 26.07.2007
Beiträge: 3.430
Entwicklungsumgebung: VS 2010 PRO
Herkunft: Naturns - Südtirol - Italien


michlG ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hi,

Zitat:
Wäre es aber nicht möglich, die Waitform in einen eigenen Thread zu erzeugen und keinen Parent zuzuweisen, so das es völlig autark ist. Nur die Show/Hide Methoden müßten dann noch über Invoke aufgerufen oder überschrieben werden.

Sofern es sich um ein eigenständiges Form handelt wäre das schon möglich.
Aber das ist doch nicht der Sinn der ganzen Sache.
Denn die GuiElemente sollen immer alle im selben Thread liegen.
Deshalb würde ich dieses Fenster mit dem GUI-Thread erstellen.

Anschliessend führst du deine Berechnungen in einen weiteren Thread aus.
Sobald dieser seine Aufgabe erledigt hat, rufst du eine Methode auf, die das Loading-Fenster über Invoke schliesst.

mfg
michlG
15.05.2008 23:03 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
herbivore
myCSharp.de-Poweruser/ Experte

avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 49.464
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin


herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo theflyer,

im Prinzip könntest du das Waitform komplett in einen Thread auslagern (der dann natürlich selbst Application.Run ausführen muss). Und dann läuft das Wait-Form unabhängig von dem eigentlichen GUI-Thread *und* muss das auch. Es darf dann (ohne Control.Invoke) keine Zugriffe von dem eigentlichen GUI-Thread auf das Wait-Form geben und umgekehrt. Inbesondere darf der Owner des Wait-Forms nicht auf ein Fenster im eigentlichen GUI-Thread gesetzt werden.

Nur der Effekt der ganzen Aktion ist immer noch begrenzt. Denn es wird nur die Blockierung des Wait-Forms verhindert. Wenn im eigentlichen GUI-Thread langlaufende Aktionen ausgeführt werden, dann blockiert das eigentliche GUI weiterhin. Mit alle Schikanen, also inkl. nicht aktualisierten Fenster, "Keine Rückmeldung" im Taskmanager usw.

Daher ist es dringend zu empfehlen, die "Progger" bei dir anzuhalten, die Regeln der GUI-Programmierung einzuhalten. Also inbesondere keine langlaufenden Aktionen im GUI-Thread auszuführen. Siehe  [FAQ] Warum blockiert mein GUI?

herbivore
15.05.2008 23:03 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
theflyer
myCSharp.de-Mitglied

Dabei seit: 07.05.2007
Beiträge: 15
Entwicklungsumgebung: VS C# 2005
Herkunft: Münster

Themenstarter Thema begonnen von theflyer

theflyer ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hi,

Zitat:
Aber das ist doch nicht der Sinn der ganzen Sache.
Denn die GuiElemente sollen immer alle im selben Thread liegen.

das ist natürlich richtig, das Problem ist, das das Fenster an 50 verschiedenen Stellen aufgerufen wird.
Das Auslagern in eigene Threads hat natürlich auch einige Änderungen in der Codelogik zur Folge. Und dann kommt man in Erklärungsnöte, wenn ein Programm was sonst einigermaßen läuft, haufenweise Fehler produziert, nur weil du ein nettes Gimmick einbauen wolltest....

Gruss
theflyer
15.05.2008 23:21 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
michlG michlG ist männlich
myCSharp.de-Poweruser/ Experte

avatar-2909.png


Dabei seit: 26.07.2007
Beiträge: 3.430
Entwicklungsumgebung: VS 2010 PRO
Herkunft: Naturns - Südtirol - Italien


michlG ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hi,

Zitat:
Und dann kommt man in Erklärungsnöte, wenn ein Programm was sonst einigermaßen läuft, haufenweise Fehler produziert, nur weil du ein nettes Gimmick einbauen wolltest....

ja, das stimmt. Denn wenn ein Programm nicht von Anfang an gut strukturiert wird, dann wird es sehr schwierig.
Es würde zwar einiges an Aufwand bedeuten, das alles umzubauen, das würde sich aber auf jeden Fall lohnen.

Denn momentan wird das Programm wahrscheinlich auch nicht wirklich stabil laufen. Versuche mal, wenn das Ladefenster geöffnet ist darauf zu klicken. Wenn sich das Programm dabei aufhängt (was ich vermute) dann kannst du die anderen Programmierer sicher von deinem Vorhaben überzeugen.

mfg
michlG
15.05.2008 23:34 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Andreas.May Andreas.May ist männlich
myCSharp.de-Mitglied

avatar-2474.gif


Dabei seit: 07.09.2006
Beiträge: 915


Andreas.May ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hrm, einen eigenen GUI Thread kannst du z.B. wie folgt erzeugen:

C#-Code:
private static WPopUp m_wndPopUp;

        private WPopUp()
        {
            // register components
            this.InitializeComponent();
        }

        private static void Init()
        {
            if (m_wndPopUp == null)
            {
                m_wndPopUp = new WPopUp();
                Application.Run();
            }
        }
        /// <summary>
        ///
        /// </summary>
        public static void ShowAsGUIThread()
        {
            new Thread(new ThreadStart(Init)).Start();
        }

Hier wird verhindert das ausser über die statische Methode ShowAsGUIThread das Popup (WaitForm) nicht initalisiert werden kann und ebenso wird damit überprüft ob das Form bereits schon instanziert ist.

C#-Code:
public static IPopUp Instance
        {
            get { return m_wndPopUp; }
        }

Sollte man das WaitForm von aussen ansprechen wollen, so kann man auf nur die Threadsicheren Methoden zugreifen indem man die Instanz über eine Schnittstelle anspricht.

Denke so solltest die meisten überzeugen können das nichts schief geht. Ansonsten muss nur noch das von herbivore angesprochene beachtet werden. Man kann aber auch etwas schummeln sollte Quellcode vorhanden sein den man absolut nicht verändenr darf / kann der blockiert indem man folgendes ausprobiert:

C#-Code:
RECT rec = new RECT();
                    GetWindowRect(hWnd, ref rec);
                    RedrawWindow(hWnd, ref rec, IntPtr.Zero, (uint)RDW_VALIDATE | RDW_UPDATENOW);

Via Win API kann man das entsprechende Fenster im WaitForm mit RedrawWindow neu Zeichnen lassen - selbst wenn dort im GUI Thread ein längerer Prozess am rumwerkeln ist. Allerdings ist das nen ziemlich schlechter stiel ;-)
16.05.2008 10:32 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Riv3r Riv3r ist männlich
myCSharp.de-Mitglied

Dabei seit: 13.06.2007
Beiträge: 206
Entwicklungsumgebung: Visual Studio 2008 Prof


Riv3r ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Guten Tag,

schau dir mal  [gelöst] Datenabruf aus DB soll in Thread ausgelagert werden an...

Gruß,
Max
16.05.2008 11:54 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
theflyer
myCSharp.de-Mitglied

Dabei seit: 07.05.2007
Beiträge: 15
Entwicklungsumgebung: VS C# 2005
Herkunft: Münster

Themenstarter Thema begonnen von theflyer

theflyer ist offline

Es geht, aber....

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

.... es ist aber ziemlich mühselig...

Bin mit Andreas Beispiel angefangen, und landete gleich auf den Bauch:
Ich konnte das Application.Run nicht einbauen, da es schon an anderer Stelle gestartet war, also erzeugte der Thread das Fenster und stoppte am Ende der Init-Funktion. Dadurch zeichnete sich das Fenster nicht mehr neu und ließ sich auch nicht mehr ansprechen.

Also hielt ich den Thread in einer while-Schleife am Leben.
Nach dem Umbau sah der Code dann so aus:

C#-Code:
private void InternalShow()
{
lblDescription.Text = Message;
Visible = true;

while (Visible)
{
Refresh();
Thread.Sleep(50);
}
}


/// <summary>
/// Zeigt das Wartefenster mit einer Meldung an
/// </summary>
/// <param name="Text">Der Text, der angezeigt werden soll.</param>
public static void Show( string Text )
{
if (_Instance == null)
{
_Instance = new StatusForm();
_Instance.Message = Text;
new Thread(new ThreadStart(_Instance.InternalShow)).Start();
}
}

public new static void Hide()
{
MethodInvoker UIDelegate = new delegate
{
Close();
}
Invoke( UIDelegate);
}

Die Eingangsroutine ist die statische Methode Show.
Die prüft zunächst, ob schon eine Instanz dieses Fensters erzeugt ist ( wollte sichergehen, das es immer nur ein Fenster gibt ), speichert den zukünftigen Text in der Variable Message. Den Text konnte ich erst innerhalb des Threads zuweisen, da sonst möglicherweise schon ein Fensterhandle im falschen Thread erzeugt wird. Danach wird der Thread gestartet.
Die Threadmethode macht das Fenster sichtbar, weist den Text zu und kurvt in einer Endlosschleife, bis von außen die Methode Hide kommt und das Fenster schließt.
Das ganze dann kompiliert und ausgeführt, das Fenster wurde sichtbar und eine Animation ( die hier nicht weiter von belang ist ) liefen prima. Also Fenster wieder schließen und .... nichts tat sich mehr, das Programm blieb hängen.
Ich fand heraus, das es beim Invoke hängenblieb. Genau weiß ich nicht warum, ich vermute das der Thread gerade schläft, wenn ich das Invoke aufrufe.
Also kam ich auf eine nicht sonderlich elegante Methode: Ich baute Hilfsvariablen wie ShouldClose und ShouldVisible ein, die dann Problemlos aus anderen Threads gesetzt werden konnten und dann in der Threadschleife behandelt wurden. Die Methode Hide sah dann so aus:

C#-Code:
/// <summary>
/// Schließt das Statusfenster wieder
/// </summary>
public static new void Hide()
{
if( _Instance!=null )
_Instance._ShouldClose = true;
}

Die Show Routine blieb wie sie war, nur meine Internalshow änderte sich drastisch

C#-Code:
private void InternalShow()
{
lblDescription.Text = Message;
Visible = true;

while (_ShouldClose==false)
{
if (lblDescription.Text != Message)
lblDescription.Text = Message;

if (_ShouldTopMost != TopMost)
TopMost = _ShouldTopMost;

if (_ShouldVisible != Visible)
Visible = _ShouldVisible;

Refresh();
Thread.Sleep(50);
}
_Instance = null;
Close();
Dispose();
}

Bei jedem Schleifendurchlauf wurde geprüft, ob sich der Text verändert hatte. TopMost gibt an, das das Fenster immer in Vordergrund bleibt und das ShouldVisible gibt an, ob das Fenster vorübergebend unsichtbar gemacht werden soll. Warum ShouldVisible und TopMost ? Beim Erzeugen des Fensters wird dem Wait-Fenster kein Parent mitgegeben, da es für sich alleine laufen muss und nichts mit der UI-Thread zu tun haben durfte.
Leider hat die Sache nur einen Schönheitsfehler: Da die Fenster nichts miteinander zu tun haben, überdecken sie sich gegenseitig, je nachdem wer den Focus bekommt. Ich konnte das WaitFenster zwar TopMost machen, dadurch war es aber immer sichtbar, auch wenn ein ganz anderes Programm im Vordergrund ist.
Kurzum, so völlig autark konnte das Fenster nun auch wieder nicht laufen, aber den Parent konnte ich dem Fenster ja auch nicht zuweisen.
Die Lösung war dann, das ich die HauptMessage-Schleife des Elternfenster auf relevante Ereignisse abhöre. Das sieht dann so aus

C#-Code:
// <summary>
/// Zeigt das Wartefenster mit einer Meldung an
/// </summary>
/// <param name="Text">Der Text, der angezeigt werden soll.</param>
public static void Show( Form Parent, string Text )
{
if (_Instance == null)
{
_Instance = new StatusForm();
_Instance.Message = Text;
_Instance.SetParent(Parent);
new Thread(new ThreadStart(_Instance.InternalShow)).Start();
}
}

Die Methode Show unterscheidet sich zu vorher nur in der zusätzlichen Methode SetParent

C#-Code:
private void SetParent(Form NewParent)
{
_ParentWndProc = new WndProcCallBack(Parent_WndProc);
AssignWndProc( NewParent);

_Parent = NewParent;
}

protected virtual void AssignWndProc( Form Parent )
{
_OrgWndProc = Win32.SetWindowLong(Parent.Handle, -4, _ParentWndProc);
}

protected virtual void ReleaseWndProc(Form Parent)
{
Win32.SetWindowLong(Parent.Handle, -4, _OrgWndProc);
}

Die Setparent prüft ruft AssignWndProc auf und speichert den Parent Objektverweis in eine Variable.
AssignWndProc besteht nur aus einer einzigen Zeile, der API Methode SetWindowLong. Diese Methode leitet alle Nachrichten vom Elternfenster in die Methode Parent_WndProc um.

C#-Code:
protected IntPtr Parent_WndProc(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam)
{
IntPtr Result = Win32.CallWindowProc(_OrgWndProc, hWnd, Msg, wParam, lParam);

switch (Msg)
{
case Win32.WM_NCACTIVATE:
_ShouldTopMost = (int)wParam == 1 ? true : false;
break;

case Win32.WM_CLOSE:
_ShouldClose = true;
break;

case Win32.WM_WINDOWPOSCHANGED:
Win32.WINDOWPOS wp = new Win32.WINDOWPOS();
wp = ( Win32.WINDOWPOS )Marshal.PtrToStructure(lParam, typeof(Win32.WINDOWPOS));

_ShouldVisible = (wp.x != -32000); // Hauptfenster minimiert

if (_ShouldVisible)
_ShouldTopMost = true;

break;
}

return Result;
}

Diese Funktion horcht nun, ob das Fenster deaktiviert wird ( WM_NCACTIVATE ) und schaltet dann das Topmost ein oder aus.
Wird das Elternfenster geschlossen ( WM_CLOSE ), wird das Flag zum Schließen des Waitfensters gesetzt. Beim Minimieren ( WM_WINDOWPOSCHANGED )
muss natürlich auch das Waitfenster unsichtbar werden ( ShouldVisible )

So, das ganze ist ein bißchen länger geworden. Ich habe das deshalb mal so ausführlich geschrieben, da ich mit dem Design gar nicht zufrieden bin, mir aber auch nichts besseres einfiel. Aber vielleicht hat ja der ein oder andere noch eine Idee...

Gruß
Stefan
20.05.2008 22:29 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
herbivore
myCSharp.de-Poweruser/ Experte

avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 49.464
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin


herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo theflyer,

ich habe nicht alles gelesen, nur den Anfang von mehrfach aufgerufenen Application.Run und while-Schleifen, um Threads am leben zu halten. Alles Mist. Siehe  [FAQ] Warum blockiert mein GUI? für eine korrekte Aufteilung der Anwendung in Threads, die den ganzen Mist unnötig macht.

Es ist ganz einfach: Das GUI sollte komplett in *einem* Thread laufen. Alle langlaufenden Aktionen müssen in einen (oder mehrere) Thread(s) ausgelagert werden.

herbivore
21.05.2008 08:00 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Andreas.May Andreas.May ist männlich
myCSharp.de-Mitglied

avatar-2474.gif


Dabei seit: 07.09.2006
Beiträge: 915


Andreas.May ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hrm, habe mir den Code mal angesehen und leide rbist immer noch auf dem selben GUI Thread, darum konntest auch kein Application.Run() verwenden. Und deshalb brichst dir auch einen ab bei der gesammten Kommunikation.

Hier mal nen Copy&Paste Beispiel.
Mach dafür einfach mal nen neues Projekt als Windows Forms Application - standardmäßig wird Form1 erstellt und die Klasse Programm, in der Klasse Programm wird in Main via Application.Run(new Form1()); aufgerufen.

Erstell nun einfach eine zusätzliche Form2 und kopiere den Code mal rein.

C#-Code:
    public partial class Form2 : Form
    {
        private static Form2 m_frm2 = null;

        private static void Init()
        {
            if (m_frm2 == null)
            {
                Application.Run(new Form2());
            }
        }
        /// <summary>
        ///
        /// </summary>
        public static void ShowAsGUIThread()
        {
            new Thread(new ThreadStart(Init)).Start();
        }

        private Form2()
        {
            InitializeComponent();
        }

    }

Geh dann in Form1 und kopiere diesen Code mal rein:

C#-Code:
        public Form1()
        {
            InitializeComponent();
            Form2.ShowAsGUIThread();
        }

Und wenn nun das ganze mal debbugst und mit Spy++ ansiehst wirst sehen beide haben andere Threads gehören aber zum selben Prozess.


Wie gesagt der Trick um nun mit Form2 zu Komunizieren besteht darin Form2.Instance ein Statisches Propertie aufzurufen das statt Form2 zurückzugeben, nur ein Interface zurückgibt mit begrenzten Methoden und Properties. Wie die Properties bzw. Methoden dann angesprochen werdne müssen sieht über den Link von herbivore.

Einen eigenen GUI Thread zu erzeugen ist somit ganz einfach, es kommt immer nur darauf an ob dieser einen Sinn hat oder nicht.
21.05.2008 10:37 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
herbivore
myCSharp.de-Poweruser/ Experte

avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 49.464
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin


herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Andreas.May,

Zitat:
Einen eigenen GUI Thread zu erzeugen ist somit ganz einfach, ...

es ist auch ganz einfach ein Programm mit gotos zu schreiben, viel einfacher als ein Programm nur mit strukturierten Konstrukten wie if, while, ..., weil man eben beliebig springen kann, und damit weniger Einschränkungen unterliegt, ...

Zitat:
... es kommt immer nur darauf an ob dieser einen Sinn hat oder nicht.

... nur macht das keinen Sinn. Genauso ist das mit mehreren GUI-Threads. Mehrere GUI-Threads machen keinen Sinn. Insofern ist es genausowenig hilfreich zu zeigen, wie man mehrere GUI-Threads erstellt, wie zu zeigen, wie man mit goto programmiert. Das ist allenfalls von theoretischem, aber keinesfalls von praktischem Interesse. Zudem zeugt deine Umsetzung mit der statischen Property Form2.Instance, sorry, nicht gerade von guten Programmierstil.

herbivore
22.05.2008 07:02 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
FZelle
myCSharp.de-Poweruser/ Experte

Dabei seit: 23.04.2004
Beiträge: 9.813


FZelle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

@theflyer:

Eine "einfachere" Lösung ist es, dem WaitForm einfach einen delegaten mitzugeben,
der dann in einem extraThread ausgeführt wird.
22.05.2008 09:35 Beiträge des Benutzers | zu Buddylist hinzufügen
theflyer
myCSharp.de-Mitglied

Dabei seit: 07.05.2007
Beiträge: 15
Entwicklungsumgebung: VS C# 2005
Herkunft: Münster

Themenstarter Thema begonnen von theflyer

theflyer ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Andreas,

habe das Programm mal umgebaut, hat prima geklappt. Konnte dadurch die ganzen Hooks und Hilfsvariablen wieder rauswerfen. Allerdings muss die Events vom Parent immer noch extra behandelt werden.

Ich teile nicht die Ansicht von herbivore, es gibt Situationen, da macht es Sinn.
Eine statische Instance finde ich auch keinen schlechten Programmstil, sondern eine Notwendigkeit, wenn ein Objekt oder Fenster nur einmal existieren soll.

Ich habe das Projekt mal mit drangehangen, vielleicht hilft es ja den ein oder anderen.
Bitte beachtet aber, das dies eigentlich nicht der richtige Weg ist. Normalerweise gehören die langandauerende Prozesse in einen extra Thread gepackt und nicht die GUI Aktualisierung. Manchmal fehlt jedoch der Source-Code oder - wie bei uns - ist der Aufwand einer Codeänderung zu hoch.
Im Projekt wird ein AnimationsControl von Codeprojekt benutzt. Wenn jemand deswegen bedenken hat, kann man sich den Quellcode bei Codeprojekt selbst runterladen  How to write a loading circle animation.

Gruß
Stefan


Dateianhang:
unknown WindowsApplication7.zip (33 KB, 272 mal heruntergeladen)

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von theflyer am 24.05.2008 20:04.

23.05.2008 13:20 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
JAck30lena JAck30lena ist männlich
myCSharp.de-Team

avatar-2653.jpg


Dabei seit: 01.10.2006
Beiträge: 11.397
Entwicklungsumgebung: Visual Studio 05/08/10 Prof.


JAck30lena ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat:
Eine statische Instance finde ich auch keinen schlechten Programmstil, sondern eine Notwendigkeit, wenn ein Objekt oder Fenster nur einmal existieren soll.

eine instanz eines objektes das nur einmal exitieren soll nennt man singleton und ja in seltenen fällen macht es sinn aber bei einer form macht es keinen sinn.

genauso teile ich die ansicht mit herbivore und hunderten von entwicklern, das mehrere gui threads genausowenig sinn machen. unter anderem sollen jegliche userinteraktionen immer nur im gui-thread stattfinden und das ist auch die ansicht von microsoft und wiederum von hunderten von entwicklern.

das was du hier gemcht hast nennt man "dirty hack" weil es das problem nciht beseitigt sondern umgeht und das wiederrum macht meistens zu späteren zeitpunkten probleme ungeahnten außmases.
23.05.2008 13:37 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
theflyer
myCSharp.de-Mitglied

Dabei seit: 07.05.2007
Beiträge: 15
Entwicklungsumgebung: VS C# 2005
Herkunft: Münster

Themenstarter Thema begonnen von theflyer

theflyer ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat:
eine instanz eines objektes das nur einmal exitieren soll nennt man singleton und ja in seltenen fällen macht es sinn aber bei einer form macht es keinen sinn.

Danke, ich habe das Buch von Gamma/Vlissides auch. Bei dieser Form macht es schon Sinn. So wird sichergestellt, das es immer nur ein "Warten-Fenster" gibt, egal aus welcher Dll es aufgerufen wird.

Zitat:
das was du hier gemcht hast nennt man "dirty hack" weil es das problem nciht beseitigt sondern umgeht und das wiederrum macht meistens zu späteren zeitpunkten probleme ungeahnten außmases.

Den dirty hack muss ich mir wohl gefallen lassen, aber die konsequenzen an 50 Stellen die Codelogik zu ändern, wiegt weit schwerer. Natürlich fällt es leicht den Zeigefinger zu erheben und zu sagen: "Das habt Ihr aber nicht sauber geplant". Aber die ersten Module sind 2002 entstanden, da hatte kaum einer was von Illegal Cross Threading gehört und uns ging es damals in erster Linie darum, die Geschäftsprozesse sauber hinzubekommen und nicht was in "irgendeinen" Wartenfenster passiert.
23.05.2008 18:49 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
herbivore
myCSharp.de-Poweruser/ Experte

avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 49.464
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin


herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo theflyer,

Zitat:
Aber die ersten Module sind 2002 entstanden, da hatte kaum einer was von Illegal Cross Threading gehört ...

den Einwand würde ich nicht so ohne Weiteres gelten lassen. Schon Win32 war single threaded und schon unter Win32 (also ab Windows 95) waren Threads nötig, um das Blockieren des GUIs sicher zu verhindern. Windows-Forms basiert ja auch Win32 und hat daher die "Einschränkung", dass alle GUI-Zugriffe aus dem GUI-Thread erfolgen müssen, geerbt.

Es bestand also "schon immer" die Notwendigkeit mehrere Threads zu verwenden und gleichzeitig waren "schon immer" threadübergreifende Zugriffe verboten.

Insofern musst du es dir schon gefallen lassen, wenn ich sage, dass ihr euch offensichtlich damals nicht ausreichend informiert habt. Leider passiert das auch heute immer noch, dass Leute einfach anfangen zu programmieren, ohne sich vorher ausreichend mit den Grundlagen zu beschäftigen.

Versteh mich nicht falsch. Ich will dich hier nicht an den Pranger stellen und ich habe Verständnis dafür, dass man in einer verfahrenden Situationen manchmal zu "dirty hacks" greifen muss, um den Aufwand in vertretbaren Grenzen zuhalten.

Nur habe nicht das geringste Verständnis dafür, dass du dein Dein Projekt hier als (gute?) hilfreiche Lösung präsentiert. Dadurch entsteht der Eindruck, es wäre ok, das so zu machen, wie du vorschlägst. Und das ist es eben nur, wenn man so im Schlamassel steckt, wie du das tust.

Wenn man ein neues Projekt angeht, sollte man von vorneherein und konsequent, die Regeln in  [FAQ] Warum blockiert mein GUI? und  [FAQ] Controls von Thread aktualisieren lassen (Control.Invoke) einhalten. Also insbesondere nur einen GUI-Thread verwenden und langlaufenden Aktionen (und nur die) in extra Threads auszulagern.

herbivore
24.05.2008 06:56 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Andreas.May Andreas.May ist männlich
myCSharp.de-Mitglied

avatar-2474.gif


Dabei seit: 07.09.2006
Beiträge: 915


Andreas.May ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Na ja die Vorposter haben alle sammt schon recht.

Nur ganz ehrlich, greife manchmal lieber zu nen kleinen Trick als das mich dran mache ganze Programme umzuschreiben die ich zumeist nichtmal selber Programmiert habe und teilweise zwischen C++ und C# kunterbunt hin und herwechseln. Ich denke genau das ist halt auch hier der Punkt.

Denke darum war auch die Frage "eigener GUI" Thread, ich beantworte nur Fragen so gut wie ich kann und wie es die Zeit erlaubt :-)
25.05.2008 23:10 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 11 Jahre.
Der letzte Beitrag ist älter als 11 Jahre.
Antwort erstellen


© Copyright 2003-2019 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 16.11.2019 23:14