Dann werde ich das wohl auch so machen müssen. Ich hatte gedacht, das geht etwas schneller (einfacher). Ich will damit nicht sagen, dass es kompliziert ist, ich hatte nur gehofft, dass ich ein event übersehen hätte...
Gruß
gremgiz
Warum es sich nicht ändrt, habe ich gefunden. Das geht nun. Jedoch bin ich der Meinung, dass dies Overkill ist ist, zumal dort auch händisch Text eingetragen wird. Im Ereignis für TextChanged werden auch andere Dinge gemacht. Die flimmert damit schon leicht. Wenn nun bei jedem eingegebenen Buchstaben die Zuweisung des Fonts auch noch gemacht wird, flimmert es mehr. Weiterhin verliere ich die bereits erstellten Formatierungen (z.B. Textfarbe). Wenn ich das auch noch im TextChanged Event abfange, kann man nicht mehr flüssig arbeiten. Es gibt doch eigentlich für alle Satndardsachen Events - nur für Copy&Paste nicht - das kann ich nicht glauben
Gruß
gremgiz
Hallo,
ich habe in einer Form diverse RTF Boxen, die teilweise via Copy&Paste befüllt werden. Dabei ist zu beaobachten, dass logischwerweise auch der Font des Originaltextes verwendet wird. Wie kann ich es erreichen, dass nach dem Einfügen der Text im richtigen - von mir definierten - Font dargestellt wird? Event TextChange hilft nicht - greift wahrscheinlich zu spät. Einen Eventhandler für Paste habe ich nur in WPF gefunden, was aber nicht verwendet wird.
Kennt jemand einen Trick?
Danke
gremgiz
Hallo kleineseichhörnchen,
wenn das mal so einfach wäre. Ich habe schon viele graue Haare darüber bekommen. Interop ist prinzipiell möglich, aber nur für das direkte Senden. Wenn die E-Mail noch im Client bearbeitet werden soll, müssen einige Properties gesetzt werden. Das geht nicht über C# (die sind schreibgeschützt) wohl aber über VB. Ich vermute das hier der Mischmasch aus COM/OLE in C# hier massiv reinfunkt. Reines COm ist leider nicht möglich und reines OLE auch nicht. Irgendwas geht da nicht. Auf Wunsch kann ich dir einige Threads nennen, die sich damit beschäftigen und auch Beispielcode
Hallo,
ich glaube, ich habe den Fehler gefunden. Es sind weder die User Objekte, noch die GDI Objekte die überlaufen. Ich schrieb ja bereits, dass der Crash auch passiert, wenn die Objekte deutlich unterhalb der Schwelle von 10000 liegen. Vielmehr war es eine DLL, die zu langsam zu sein scheint. Wird eine Anfrage abgeschlossen, werden 2 E-Mails generiert und an Lotus Notes gesendet. Hierbei scheint er sich zu verschlucken. Der erste Test ohne E-Mail-Generierung verlief positiv. Dann habe ich nach jeder E-Mail eine Pause von 2s eingefügt und es lief immer noch. Damit würde ich sagen, ist dieses Problem gelöst.
Ich habe mir den ganzen Fehlercode noch mal angesehen. Der Crash passiert an Adresse 0x2. Das ist ein geschützter Speicher und Windows scheint hat eigentlich richtig gehandelt, da an dieser Stelle kein Fenster gespeichert werden darf, kam die Meldung 😦.
BTW: Die DLL ist in VB geschrieben, da es C# scheinbar unmöglich ist, sauber mit Lotus Notes zu kommunizieren. Kenn jemand von Euch einen Weg, wie das geht. Es geht dabei nicht um das reine Senden – das ist kein Problem. Vielmehr soll die E-Mail in Lotus Notes angezeigt werden, dort ggf. weiterbearbeitet werden und dann gesendet werden.
Danke für Eure Hilfe
Gruß
gremgiz
Der Witz an dieser Access Vioations ist, dass diese laut MS nur in unmanaged Code auftreten kann, der gar nicht verwendet wird...
Nun gut…
Dazu ein wenig Hintergrund. Es handelt sich um eine Applikation für Kundenanfragen. Beim Öffnen der Applikation wird ein erster Tab erzeugt, der die Anzahl aller fälligen Aktionen anzeigt. Ein Klick auf eine dieser Zahlen (Button) öffnet eine Tabelle in einem neuen Tab mit einer groben Übersicht aller Anfragen, die es zu bearbeiten gilt. Ein Doppelklick auf eine Zeile öffnet die Anfrage wiederum in einem neuen Tab. Hier kann nun damit so einiges gemacht werden.
Wie kann ich den Fehler erzwingen: Öffnen einer Anfrage, ändern von Werten und abspeichern. Danach wird die nächste Anfrage geöffnet usw. Die einzelnen Anfragen werden nach dem Speichern nicht zwangsläufig geschlossen, sondern können offen bleiben.
Es ist auch schon vorgekommen (gerade eben), dass nur eine Anfrage geöffnet war und gespeichert wurde. Dabei blieb es dann hängen. Es waren zu diesem Zeitpunkt 200 GDI Objekte und 300 User Objekte geöffnet (3 Tabs). Der Absturz kommt aber nicht zwangsläufig beim Speichern, sondern manchmal auch wenn ich eine neue Anfrage öffne oder eine geöffnete bearbeite.
Folgende Fragen stellen sich:
Wie kann ich es am elegantesten erreichen, den Inhalt eines Tabs zu entladen, wenn dieser nicht in der aktive ist, ohne den Tab selber komplett zu zerstören und wie bekomme ich die Daten wieder rein? Das Ganze soll nach Möglichkeit nicht unendlich lange dauern.
Beim Laden eines Tabs für eine Anfrage passiert folgendes:
Hallo,
für alle die es interessiert, wie man den GDI Stack erhöht: To change this limit, set the following registry value
Ich teile aber die Meinung, dass dies den crash nur hinauszögert. Einige weitere Untersuchungen mit dem taskmanager haben ergeben, dass ich die GDI Objekte wieder freigebe, so wie ich es auch eigentlich gedacht hatte. Wird eine Form geladen erhöhen sich die GDI Objekte entsprechend ud wenn die Form wieder geschlossen wird, verringern sie sich wieder. Was ich erstaunlich finde, ist, dass er den Speicher nicht freigibt, oder nur partiell.
Wie ich den Fehler erzwingen kann, kann ich euch zwar mitteilen, das wird Euch aber nichts nutzen, da dies Applikationsabhängig sein dürfte
gruß
ps: es gibt noch einen trick oder besser gesagt einen hack, wie man den gdi stack erhöhen kann. auf codeproject findest du eine anleitung.
Hast du zufällig die URL parat?
@kleines_eichhoernchen: Nein, reine Single Thread Anwendung und SDI. Die einzige Stelle, an der ich mal einen Inoke verwende ist ein Fortschrittsbalken
Hallo,
@dN!3L: Wann immer es geht, gebe ich die Objekte wieder frei. Um bei Deinem Beispiel des Fonts zu bleiben: In der gesamten Anwendung gibt es nur einen Font, der direkt in den Steuerelementen festgelegt ist. Für Ausnahmen, wo ich ihn mal aufrufen muss, ist er nur einmal im Code verankert und referenziert dann auf die neuen Objekte
Die GDI Objekte kommen alle aus dem Designer. Selbstgezeichnet wird nix. Wann und wie oft, hängt vom Anwender ab. Der entscheidet wann er welchen View benötigt. Die Views selbst können umfangreich sein. Ich glaube der Spitzenreiter liegt bei 80 Controls – und nein, diese Flut kann nicht eingedämmt werden
Hallo
Alternativ hätte ich noch folgendendes von Windgb
Fehlermeldung:
(135c.14dc): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000a8f ebx=c7f60005 ecx=0000011e edx=00000000 esi=0c814328 edi=c7f60000
eip=7713205b esp=002e950c ebp=002e9540 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
ntdll!RtlpLowFragHeapFree+0xc5:
7713205b 8930 mov dword ptr [eax],esi ds:0023:00000a8f=????????
0:000> !pe
Exception object: 106ca304
Exception type: System.AccessViolationException
Message: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
InnerException: <none>
StackTrace (generated):
SP IP Function
002EE2C0 6B27EC80 System_Windows_Forms_ni!System.Windows.Forms.UnsafeNativeMethods.DestroyWindow (System.Runtime.InteropServices.HandleRef)+0x10
Gruß
Hallo,
wie versprochen, der Auszug aus WinDbg.
Fehlermeldung:
Exception type: System.OutOfMemoryException
Message: Error creating window handle.
InnerException: System.NullReferenceException, use !PrintException 0b4897d4 to see more
StackTrace (generated):
SP IP Function
002E9EE8 6B2A703B System_Windows_Forms_ni!System.Windows.Forms.NativeWindow.CreateHandle (System.Windows.Forms.CreateParams)+0x28b
002EDFB0 6B2A6CB5 System_Windows_Forms_ni!System.Windows.Forms.Control.CreateHandle()+0x1250:000> !PrintException 0b4897d4
Exception object: 0b4897d4
Exception type: System.NullReferenceException
Message: Object reference not set to an instance of an object.
InnerException: <none>
StackTrace (generated):
SP IP Function
002EABC8 07828DB9 CSC_Solutions!CSC_Solutions.Program.Application_ThreadException (System.Object, System.Threading.ThreadExceptionEventArgs)+0xb9
Es hat also etwas mit dem Speicher zu tun. Hat jemand dazu Ideen?
Gruß
gremgiz
Hallo zusammen,
@ Jack30lena:mit WinDbg werde ich mal versuchen was rauszubekommen. Das Ergebnis wird dann gepostet.
@talla: Es werden schon einige GDI Objekte erzeugt. Ich würde dann aber erwarten, dass der Absturz an nahezu immer der gleichen Stelle auftritt. Nur manchmal starte ich das Programm, wähle die Funktion und schon ist es weg. Dann Neustart des Programms und es läuft. Es wurde aber keine Prozesse neu erstellt oder beendet. Ich weiß, dass Windows immer selber viel macht, aber so viel ist es auch wieder nicht. Die User Objekte bewegen sich im Rahmen von max. 4000 – also deutlich unterhalb der magischen Grenze von 10000. Die GDI Objekte sind bei ca. 500 im Maximum.
@Th69: Es sind sehr viele Controls vorhanden, die in Tabs angeordnet sind. Es gibt prinzipiell 2 Tab Controls. Ein Haupttab, der das gesamte Objekt beinhaltet und untergeordnete Tabs, die Details beinhalten. Das Laden der Tabs erfolgt dynamisch – sprich erst, wenn diese benötigt werden, werden Sie auch geladen. Das Entladen erfolgt jedoch immer erst mit Schließen des Haupttabs. Dann wird alles aus dem Speicher entfernt. Die Anzahl der Haupttabs habe ich schon begrenzt. Hilft aber nicht viel.
Gruß
gremgiz
Hallo,
Ein Programm hat ein seltsames Verhalten. So lange es im Visual Studio Debugger ausfgeührt wird, kann ich ohne Probleme damit arbeiten. Sobald aber die Anwendung verteilt wird, kommen sehr merkwürdige Abstürze. Diese passieren immer an anderen Stellen, fast niemals an der Gleichen und das sehr sporadisch. Ich habe zwar mittlerweile einen Weg gefunden, um den Fehler zu erzwingen, bekomme aber in den wenigsten Fällen eine Fehlermeldung. Wenn mal eine kommt, besagt die folgendes:
Fehlermeldung:
Fault Module name: ntdll.dll
Version: 6.1.7600.16385
Exception code: c0000005
Exception Offset: 0005205b
Gestern hatte ich noch das Glück, dass ich zumnindes mal einen Ansatz einer Fehlermeldung bekam: > Fehlermeldung:
Ein Fensterhandle konnte nicht erstellt werden sehr hilfreich, wenn man bedenkt, dass die gleiche Methode eine Minute vorher noch genau das getan hat.
Mehr leider nicht. Google hat nichts brauchbares geliefert. Der Fehler tritt unter Vista, XP und W7 auf.
Hat vielleicht irgendwer eine Idee, wo ich anfangen kann zu suchen? Ich habe schon versucht eine globale Routine zu erzeugen, die unbehandelte Exceptions abfängt, aber selbst die greift nicht mehr.
Es wird kein Multithreading verwendet, daher kann es also nicht kommen. Speicher und CPU Auslastung sind auch im Grünen Bereich.
Wenn ich versuche, nach dem Absturz das Programm zu debuggen, bekomme ich wiederum einen Fehler:> Fehlermeldung:
Unhandled Exception at 0x7713205b
Zugriffsverletzung beim Schreiben an Position 0x2
Der Assemblercode an der Stelle lautet: mov dword ptr [eax],esi
Vielen Dank im Voraus
Gremgiz
Hallo zusammen,
Aus einer Anwendung heraus soll für statistische Zwecke eine Excel-Tabelle (Excel 2003) beschrieben werden. Dabei haben einige Felder (Zellen) mehr als 255 Zeichen. Mittlerweile weiß ich, dass es dort wohl eine Begrenzung gibt; soblad die überschritten wird, gibt es eine Exception. Wie kann diese Grenze aufgehoben oder umgangen werden? Die Anzahl der Zeichen variiert, ebenfalls die Anzahl der Zeilen.
Nachtrag:
Ein wenig Spielerei brachte folgendes zu Tage:
Wird Excel über ein object[,] beschrieben kommt dieser Fehler.
Schreibe ich die Daten direkt in die Zelle (per worksheet.Cells[x,y]) kommt der Fehler nicht.
Ich würde aber gerne über object[,] gehen, da dieses performanter ist
Danke und gruß
gremgiz
Hallo,
ich habe über das Problem noch mal ein wenig nachgegrübelt.
Hierzu mal meine Gedanken. Dazu würde ich mich über Kommentare freuen:
public class Globales
{
public static Form Form1 {get; set;}
}
Dann beim Start des Programms das ganze setzen:
Globales.Form1 = new Form;
Beim Aufruf der Form das ganze wieder rausholen und das halt jedesmal:
Form Form2 = Globales.Form1;
Was ich dabei beobachtet habe ist, dass immer nur ein Tab damit befüllt wird. Alle älteren Tabs werden glöscht oder besser leer angezeigt. Keine Ahnung warum
Kann mir hier noch mal jemand gute Tipps geben?
Danke
gremgiz
Hallo Herbivore,
das war auch meine Vermutung - ist es aber nicht. Da werde ich wohl weiter suchen müssen. Vorerst habe ich mir mit einer Variable geholfen. Nicht schön aber funktionell.
BTW: Dieses Verhalten habe ich auch schon bei anderen Events beobachtet, die ich erst im Code definiere
Gruß
gremgiz
Hi,
Das ganze läuft jetzt erstmal. Jdoch wird jedes KeyDownEvent nun 2x durchlaufen? Woher kann das denn jetzt kommen?
Gruß
gremgiz
Hi,
ich habs glaube gefunden. Meine Suche innerhalb des Forums war wohl falsch. Für alle die es interssiert:
Hallo Herbivore,
leider leitet das KeyPrevent nicht durch. Mit dem rekursiv habe ich das auch schon probiert - komme aber nicht an die Kontrols, sondern nur an die übergeordneten Container, in die die Controls eingebettet sind?
So richtig fündig geworden inm Forum bin ich nicht.
Was ich probiert habe, um das ganze rekuriv zu bekommen:
foreach (Control Help_Control in UserControl)
{
Help_Control.KeyDown += new KeyEventHandler(Hotkeys);
}
Das hat mir ertsmal nen Fehler rausgeworfen: Es gibt keine öffentliche GetEnumerator Definition.
Also habe die Controls erst mal eingesammelt mit:
Control.ControlCollection UCControl = UC.Controls;
Wenn ich das ganze jetzt starte, kommt zwar kein Fehler, aber auch kein Event. Die Schleife durchläuft genau zwei Controls, nämlich die Container, die die eigentlichen Controls beinhalten.
Habe ich eine falschen Denkansatz oder mache ich grundsätzlich was falsch?
Man könnte jetzt natürlich ganz pragmatisch alle Controls per Hand hinschreiben und auf die gleiche Funktion verweisen lasse, aber das kann es ja wohl niht sein oder?
Gruß
gremgiz
Nanu, keiner hat eine Idee? Nach den Zugriffszahlen zu urteilen, bin ich aber nicht allin mit dem Problem.
Ich habe ein wenig gespielt. Wie beeits erwähnt kann ich von der Hauptform ohne Probleme auf das 1. Usercontrol zugreifen. Nur auf die eine Ebene tiefer nicht mehr.
Die einzelnen Controls innerhalb des 2. Usercontrols lassen sich ebenfalls per KeyDown Event problemlos ansprechen. Nur das will ich nicht, da nicht flexibel genug. Um dieses Evnt auswerten zu können, muss das COntol den Fokus haben, da es ja an diess gebunden ist. Daher will ich auf das gesamte 2. Usercontrol Hotkeys definien, die auch die Steuerung einzelner Buttons übernehmen.
Was ich auf keinen Fall will sind globale/systemweite Hotkeys. Die Hotkeys sind nur für die App gültig.
Wie kann ich ein /mehrere Hotkeys auf ein Usercontrol erstellen, das wiederum Teil eines Usercontrols ist?
Evtl. über eine Child/Parent Eigenschaft?
Gruß
gremgiz
Hallo zusammen,
Ich habe ien Problem mit Hotkeys. Dies wurde in vielen Threads ja bereits beleuchtet, aber ich komme nicht so recht weiter.
Beschreibung:
Wenn das Programm über eine Form gestartet wird, definiere ich dort die Hotkeys, die für ein in der Form dargestellten UserControl gelten. Dies funktioniert auch. Nun lade ich innerhalb diesees UserControls ein weiteres UserControl. In diesem UserControl gibt es z.B. eine RTF Box. In der Hauptform habe ich für ENTER einen Hotkey definiert. Wenn ich aber nun in der RTF Box Enter drücke, wird als erstes der Hotkey vom übergeordneten UserControl ausgewertet - was natürlich hier unerwünscht ist. Eigentlich ist das logisch, da die Hauptform nur das 1. UserControl aufruft und auch nur dieses kennt. Daher kann ich hier nicht abfangen, von welchem UserControl der Aufruf erfolgt. Wie kann man das umgehen? Idealerweise würde ich ganz gerne im 1. UserControl die Hotkeys für dieses UserControl und alle untergeordenten UserControls definieren. Geht das? Ein UserControl kennt ja nicht KeyPrevent
Danke
gremgiz
Hallo Herbivore,
Vielen Dank für die Tipps. Habe es mal umgesetzt und es funktioniert ganz gut.
Gruß
Gremgiz
Hallo,
@Herbivore: ob meine Lösung jetzt optimal ist, wage ich zu bezweifeln. Das ist so ziemlich meine erste Arbeit mit Threads. Hast du Vorschläge, wie man das optimieren kann? Das ganze an sich geht schneller - oder fühlt sich zumindest so an - was ja auch ein nicht zu unterschätzender Aspekt der Benutzerpsychologie ist. Genau gemessen habe ich die Zeit nicht, jedoch mal mit "mitzählen" ist die Zeit halbiert worden. Nachdem das GUI aufgebaut ist, ist es noch ca. 0,5 -1 s blockiert - bis halt alle Threads fertig sind.
@JunkyXL: Das mache ich auch so. Alle initial benötigten Controls werden geladen - der Rest später. Es bleiben aber immer noch genügend über 😃
Gruß
gremgiz
Hallo zusammen,
erst mal herzlichen Dank für die vielen Tipps und Anregungen. Ich glaube ich habe die Lösung gefunden - zumindest funktioniert es gut.
Die Ladezeiten des GUIs kann ich schlecht beeinflussen, aber ich kann das GUI im Hintergrund laden und dann holen. Grundlage für diese Überlegung und schlußendliche Umsetzung ist Controls von Thread aktualisieren lassen (Invoke-/TreeView-Beispiel). Für dieses sehr gut gelungene Tutorial herzlichen Dank an alle, die daran mitgewirkt haben
Was wird nun im Einzelnen gemacht:
Bevor ich die Schritte im Detail erläutere, die Struktur des Programms: Beim Start des Programms wird der Benutzer verifiziert. Wenn dies erfolgreich verlaufen ist, wird die Hauptmaske geladen, in der das "Problem"-GUI als Tab dargestellt werden soll. Mit Aufruf dieses Haupt-GUIs wird das „Problem“-GUI bereits das erstemal geladen. Dieses "Problem"-GUI kann vom Anwender beliebig oft aufgerufen werden. Dies erfolgt über einen Button.
public partial class Main_GUI
{
delegate void Del_LoadGUI();
}
private void Button_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(Thr_ShowGUI));
t.Start();
}
protected void Thr_ShowGUI()
{
//Den Tab anzeigen, muss separat erfolgen wegen Tread-Sicherheit
PageView();
//Im Hintergrund einen neuen Tab erzeugen
BeginInvoke(new Del_LoadGUI(Thr_LoadGUI));
}
protected void Thr_LoadGUI()
{
//Ableitungen erstellen
New_GUI Next_GUI = new New_GUI(); //Das GUI an sich
Page_Ticket = new TabControl.Page(); //Tab für das GUI
//Tabzähler erhöhen
TabCount++;
//Namen des Tabs festlegen für spätere Verwaltung
Page_GUI.Name = "Tab" + TabCount.ToString();
//Angezeigten Text des Tabs einstellen
Page_GUI.Text = "Neuer Tab";
//Tab befüllen und hinzufügen
Page_GUI.Controls.Add(Next_GUI);
Tab_Main.Pages.Add(Page_GUI);
//Tab unsichtbar machen
Page_GUI.Visible = false;
}
Definition der klassenweiten Variablen (machen das Leben leichter auch wenn nicht sauber objektorientiert)
public partial class Main_GUI
{
//Den Teil haben wir schon eingefügt
delegate void Del_LoadGUI();
//Klassenvariablen
TabControl.Page Page_GUI = null;
Int TabCount = 0;
}
private void PageView()
{
if (Page_GUI.InvokeRequired)
{
Page_GUI.Invoke(new MethodInvoker(PageView));
return;
}
Page_GUI.Visible = true;
TabControl.SelectedPage = Page_GUI;
TabControl.Update();
}
Wichtig hierbei ist das Update(); das dafür sorgt, dass das GUI direkt neu gezeichnet wird und zur Verfügung steht, bevor das neue/nächste GUI geladen wird.
private void Main_GUI_Load(object sender, EventArgs e)
{
Invoke(new Del_LoadGUI(Thr_LoadGUI));
}
Interessant hierbei ist der Synchrone Aufruf des Threads im Gegensatz zu dem sonstigen Asynchronen Aufruf. So kann man erreichen, dass die Hauptform auch sofort einsatzfähig ist und nicht erst noch hängt, weil der Thread im Hintergrund noch läuft. Klar braucht auch diese Ausführung Zeit, die man aber mittels eines Splashscreens gut abfangen kann – und es ist nur einmal beim Start des Programms.
Anmerkungen:
Da ich nicht mit den WindowsForms arbeite, sondern mit einem anderen Control Set, bin ich mir nicht sicher, ob ich in den Codebeispielen alles korrekt auf WinForms rückgeschrieben habe. Bei Bedarf kann man dies ja ändern 😃
Gruß
Gremgiz
Aus gewissen Überlegungen heraus, sind Code und GUI komplett getrennt. Das heißt, das eigentliche GUI hat weder Konstruktoren noch Events. Diese werden alle in der zugehörigen Code Klasse definiert. DIe interne Stopuhr von C# gibt mir Zeiten von 1,5 -2,5 Sekunden aus, um die Form per NEW zu erstellen und eine weitere Sekunde, um diese in ein übergeordnetes Control einzubetten.
Ich tippe mal, dass ein Backgroundworker vielleicht die Lösung ist. Damit werde ich mal rumprobieren. Wenn es weitere Hinweise gibt, wäre ich dankbar
Danke
Gremgiz
Der Tipp mit dem Link hilft leider nicht weiter. Meine Form ist ja fertig. Für einzelne Steuerelemente ist das Ok. Bei komplexen Sachen nicht mehr
Hallo Norman-Timo,
vielen Dank für die Antwort. Den Link werde ich mir anschauen. Das mit dem Vorhalten klappt leider nicht, da ich immer neue Instanzen benötige, da der benutzer in diese Form immer Daten eingibt und nicht immer alle Tabs vorher schließt
Gruß
Gremgiz
Hallo,
Ich habe eine ziemlich komplexe Form gebastelt, die an verschiedenen Stellen im programm immer wieder aufgerufen werden muss (tabbed browsing). Wenn ich die jedesmal mit form Form = new form() lade, dauert mir das zu lange. Daher ist meine Idee, das ganze bereits beim Start des Programmes zu laden und in den Speicher zu schreiben, so dass ich dann jeweils eine Kopie davon bekommen kann. Ist das möglich und wenn ja, wie sehen die Lösungsansätze dazu aus?
Hallo,
eine bestimmte Form muss einfach mehrfach anzeigbar sein. Es geht darum, dass dort Daten zu einem Vorgang erfasst werden. leider können die User das nicht immer erst zu Ende machen, sondern holen sich auch die Daten zu einem anderen Fall, der die gleiche Form verwendet. Das sollte schlicht beides angezeigt werden
Hallo zusammen,
ich habe mittlerweile ein paar Umbauten vorgenommen und so die Ladezeiten verkürzen können. Sie liegen momentan in einem akzeptablen Rahmen, sind aber noch nicht optimal.
Ich habe daher die Idee, diese Form (wird am meisten benötigt) bereits im Splashscreen komplett zu laden und in den Cache zu werfen. Dann kann ich die ja aus dem Cache holen bzw. immer eine entsprechende Ableitung erstellen. Daraus ergeben sich für mich aber ein paar Fragen:
Gruß
gremgiz
Hi,
ohne den Code zu kennen (und die Stelle) wo es knallt, kann ich nur Vermutungen anstellen. Wenn du ein externes Framework verwendest und diese Funktionen in einer DLL liegen, diese DLL aber nicht mit installiert wird, kann es dazu kommen. Ist aber nur ne Vermutung. Versuch doch mal das Verhalten bei dir auf einem frischen Rechner nachzustellen, dann siehst du wo es knallt. Wenn kein Rechner da ist, nimm VirtualBox o-ä.
Gruß
gremgiz
Hallo,
bin leider erst jetzt dazu gekommen weiter zu machen. Habe mal mit dem profiler neue Tests gemacht. Bedingt durch die Konfiguration (lasse alle Variable mittracken) habe ich die zeiten zwar nach oben schießen lassen, konnte dadurch aber besser sehen wo die Zeit liegen bleibt. Es ist in der Tat so, dass InitializeComponent(); der einzelnen Unterformulare die zeit frisst. So haben die Adressdaten eben mal 10s benötigt. Die anderen Unterformulare sind auch nicht viel weniger - und immer im InitializeComponent();. Die liegen alle bei 7-10s. Die Datenbankzugriffe die benötigt werden, um Listwerte in die Kontrols einzutragen liegen dagegen im ms-Bereich - also zu vernachlässigen.
Wenn ich mir nun die InitializeComponent(); Funktion näher ansehe, sind die größten Zeitfresser das Laden der Bildressourcen (Icons im PNG Format mit 16x16 Pixel und 256 Farben. Die Bilder sind als Ressource im Programm eingebunden. Er genehmigt sich dabei mehr als 1s.
Was vielleicht noch interessant ist: Ich verwende das KryptonToolKit. Das braucht natürlich auch noch Zeit (ca 1-2s)
Gruß
Gremgiz
@Jaensen: Die Adressen haben ein eigenes UserControl, was nur 3x aufgerufen wird. Innerhalb des Controls habe ich einen TableLayoutAdapter mit den entsprechenden Textboxen. Eigentlich doch richtig?
Versuch endete in einer noch langsameren Zeit. hatte versucht das COntrol so umzaubauen, dass weniger Platzhalte wie tablelayout etc da sind - ist aber noch langsamer.
Bin gerade am umbauen.
Ignoriert habe ich dich nicht. Zeit liegt bei ca. 0.5 Sekunden
Müssen beide UserControls direkt sichtbar sein?
Ja, das übergeordnete Control enthält die wichtigsten Daten aus den untergeordenten Controls
Vielleicht brauchst du ein CustomControl ?
Wäre durchaus denkbar - Muss ich mich aber erst mit befassen
Weißt du wieviele Instanzen der Formulare brauchst (Wieviele gleichzeitig sichtbar sein können)? ggf. kansnt du eine Instanz vorhalten?
Das Übergordnete Formular kann beliebig oft aufgerufen werden und wird es in der Praxis vermutlich auch, da die lieben Anwender immer hin und herspringen müssen, was in der Natur dieser Anwendung liegt
Was passiert während der initialisierung?
Eigentlich nichts weiter als Standard, oder was meinst du hier genau?
Fügst du die Controls dynamisch hinzu oder legst du sie schon im Designer drauf?
Beides ist möglich. Rumpf ist immer im Designer aber einige Controls kommen erst zur Laufzeit und andere werden geändert.
Kann es sein dass die controls zu spät geladen werden ?
Glaube ich nicht. Ich bin eher traurig darüber, dass ich sie zu früh laden muss, um die Kommunikation hinzubekommen. Werden direkt mit dem hauptformular geladen
Feuern unnötige Events?
Nein zu dem Zeitpunkt sind keine Events am werkeln
Nein, ich lade lediglich die Forms mit den Controls. Einige Felder werden mit Listwerten vorbelegt, die aus der DB kommen, aber das geht fix und SpeedTrace gibt da noch nicht mal ne Zeit für aus
In diesem Beitrag erwähnst du aber, dass man das mit GUIs nicht machen sollte ....
Die Anzahl der Controls lassen sich nicht reduzieren. Es handelt sich um eine ziemlich komplexe DB Anwendung. Allein der Adressbereich muss 3x ausgeführt sein, was schon 19 Controls pro Adressbereich sind
Leider hilft hier ein Splash gar nichts, da dieser ja nur am Anfang angezeigt wird. Diese Funktion kann innerhalb des Programms jedoch beliebig oft aufgerufen werden - was halt jedesmal seine Zeit dauert
gruß
PS: Ach so die Anzahl der Controls. Nicht hauen: ca. 70
Ok - Asche über mein Haupt....
Habe den SpeedTracer genommen (BTW: Das ist ein kommerzielles Produkt mit 10 Tagen Trial. Gibt es ein gutes Freeware Tool?) und mal Zeiten ermittelt. Dabei habe ich mich auf das problematische UserControl beschränkt.
Es gibt im Prinzip 2 längere Aktionen. Das UserControl selber braucht ca 1,5 Sekunden um sich zu initialisieren. Ein Unterformular, das sofort geladen werden muss braucht in etwa die gleiche Zeit. Macht also 3 Skunden für diese beiden Formulare. Der Rest ist fast vernachlässigbar.
Eine genauere Analyse erbrachte, dass das Initialisieren/Zeichnen der Steuerelemete die Zeit frisst. Nur werde ich da nicht rankommen bzw. großartig optimieren können oder?
Gruß
Gremgiz
Hallo,
kannst du das bitte etwas näher eläutern? Ich kenne diese Funktion nicht
Gruß
gremgiz
Hallo zusammen,
Ich habe ein Problem mit den Ladezeiten von Formularen. Aber der Reihe nach. Eine Applikation öffnet ein Fenster und bietet ein Menü an, mittels welchen die Funktionen aufgerufen werden. Diese Funktionen öffnen sich innerhalb eines Tabs als UserControl.
Eines dieser UserControls ist sehr umfangreich und öffnet weitere UserControls in einer separaten TAB Ansicht - da nicht alle benötigten Daten auf den Schirm passen. Da die Tabs untereinander durchaus kommunizieren, müssen die entsprechenden Ableitungen beim Start des übergordneten UserControls bereits erstellt werden. Das Zeichnen der untergeordneten UserControls erfolgt erst beim erstmaligen Aufruf, um zeit zu sparen. Jedoch benötigt das übergeordnete UserControl schon 5-6 Sekunden um sich zu öffnen. Gibt es Tricks dieses zu beschleuinigen?
Ich habe hier schon ein wenig gesucht und meine Idee mit seperaten Threads wieder fallen gelassen, da jeder davon abrät GUIs in seperaten Threads zu laden.
Vielen Dank
gremgiz
Hallo,
danke für den Tipp - funktioniert. Mal wieder den Wald vor lauter Bäumen nicht gesehen
Gruß
Gramgiz
Hallo,
ich habe ein TableLayoutPanel, dass zur Laufzeit erweitert werden kann. Wenn der Anwender nun eine falsche Eingabe macht, oder Daten verworfen werden sollen, möchte ich erreichen, dass die gesamte Zeile gelöscht wird. Wie kann ich das erreichen? Es reicht aus die letzte Zeile zu löschen, aber ich bekomme es nicht hin. Hat jemand einen heißen Tipp?
Ich habe bereits probiert, einfach den RowCount um 1 zu verringern und danach ein Update() - geht aber nicht
Danke
Gremgiz
Hallo,
scheinbar beißen sich da mehrere Leute die Zähne dran aus. Ich möchte mich erst einmal bei allen bedanken, die sich darüber den Kopf zerbrochen haben. Ich für meinen Teil habe es jetzt so gelöst, dass ich in VB eine DLL geschrieben habe, die ich über C# einbinde. Manchmal ist VB doch die bessere Alternative J
Falls noch Ideen bestehen, bitte posten.
Gruß
Gremgiz
Das es nicht der elegante Weg ist, steht außer Frage. Nur bringt mich das nicht weiter
Gruß
gremgiz
Hallo,
ja das habe ich mir angeschaut, geht aber in die falsche Richtung. Der Threat verwendet DominoObjecte (COM), was hier nicht geht. Ich muss über OLE zugreifen udn das geht leider nur auf diesem Wege.
@JayCore: Das hat mich auch ein paar graue Haare gekostet, dass so hinzubekommen. Aber irgendwo im Thread habe ich eine URL gepostet die das Grundgerüst sehr gut erklärt.
Gruß
gremgiz
Hi,
Ich habe ein wenig gespielt und herausgefunden, dass:
Type NotesSessionType = Type.GetTypeFromProgID("Notes.NotesSession");
object NotesSession = Activator.CreateInstance(NotesSessionType);
bool obj = (bool)NotesSessionType.InvokeMember("ConvertMIME", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.GetProperty, null, NotesSession, null);
Wunderbar funktioniert. Nur wenn ich danach aufrufe:
NotesSessionType.InvokeMember("ConvertMIME", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty, null, NotesSession, new object[] {false});
Knallt es mit „TargetInvocationException“. HRESULT: 0x8000FFFF (E_UNEXPECTED). Kann mir irgendjemand sagen was ich da falsch mache?