Laden...
L
Lynix myCSharp.de - Member
Software-Entwickler Saarland Dabei seit 08.04.2004 667 Beiträge
Benutzerbeschreibung

Forenbeiträge von Lynix Ingesamt 667 Beiträge

21.03.2006 - 15:27 Uhr

Hallo Kostas,

das Delegate kommt in diesem Fall nur versteckt zum Tragen. Wenn du das Event mit += abonnierst, passiert intern nix anderes, als das ein Delegate in die Event-Routine eingetragen wird.

Wird nun das Event ausgelöst, werden alle Delegates die in der "Liste" des Events stehen aufgerufen.

Wenn Du das Event abonnierst, sieht das ja in etwa so aus :

meinLager.LagerbewegungEvent += new EventHandler(OnLagerbewegung)

Der EventHandler ist das Delegate, von dem eine neue Instanz (genauer : neuer Zeiger auf eine Methoden-Instanz, nämlich der Methode OnLagerbewegung) mit new angelegt wird. Diese Instanz wird durch das += in die schon erwähnte Liste des Events eingetragen. Beim Aufruf des Events werden dann alle Delegates, die in die Event-Liste eingetragen wurden, aufgerufen.

21.03.2006 - 08:45 Uhr

Ein delegate ist quasi eine Variable in der Du die "Instanz" einer Methode speichern kannst. (Genauer : Einen "Zeiger" auf eine Methoden-Instanz).

Rufst Du das Delegate auf, wird die Methode ausgeführt auf die das Delegate zeigt.

Das kann recht nützlich sein um z.B. einen Callback zu realisieren : Du rufst eine Methode in einer Logik-Klasse auf und gibst einen Delegate als Parameter mit. Die Methode kann dann z.B. das Delegate aufrufen, wenn irgendwas schief gelaufen ist, oder wenn die Methode asynchron abläuft, um bescheid zu geben, dass sie fertig ist.

Wenn Du Funktionszeiger aus C++ kennst, dann kannst Du Delegates auf C#-Seite in etwa genauso betrachten, obwohl beide Konzepte nicht identisch sind.

08.03.2006 - 11:34 Uhr

Dann bist Du vielleicht in einem 10tel der Zeit fertig, aber zumindest was Remoting angeht wird deine Anwendung mit an Sicherheit grenzender Wahrscheinlichkeit auch 10 Mal so langsam laufen, als wenn Du es anständig von Hand programmierst.

Remoting wird bei größer werdenden Datenmengen, die übertragen werden müssen überproportional langsamer. Würde ich (nachdem ich bereits damit auf die Schnauze gefallen bin) heute maximal noch für kleine Mini-Projekte benutzen.

08.03.2006 - 11:31 Uhr

Abstrakte Typen können nicht mit dem XMLSerializer serialisiert werden. Auch Typen, in denen z.B. als Member abstrakte Typen vorkommen können nicht XML-serialisiert werden.

Da hilft dann nur noch Binary Serialization.

08.03.2006 - 11:29 Uhr

Ein einfaches Beispiel wo man dieses using häufig sieht ist bei der Verwendung von Funktionen File.Exists oder Directory.Exists

Wenn man nach der Verwendung einer dieser Funktionen nicht explizit dafür sorgt, dass das Handle auf die Datei / das Verzeichnis wieder freigegeben wird, ist die Datei anschliessend einfach für alle weiteren Zugriffe gesperrt.

Da File.Exists bzw. Directory.Exists statische Methoden sind, gibts leider keine Möglichkeit explizit ein Dispose aufzurufen daher hilft da nur noch die Definition eines using-Blocks. Dieses sorgt dann dafür, dass die Datei / das Verzeichnis am Ende des Blocks wieder freigegeben wird.

08.03.2006 - 11:26 Uhr

Nein, sorry - ich meinte natürlich regsvr32.exe

08.03.2006 - 11:25 Uhr

Argh Excel aus C# benutzen. Da kann ich mich noch dunkel erinnern an Fehlermeldungen so in der Art "Dieses Objekt befindet sich in einem Zombie-Zustand"...

Wir haben halt drüber gelacht und dann VB6 dafür benutzt...

08.03.2006 - 11:22 Uhr

Wenn die Assembly (SharpUSBLib) ein .NET-Wrapper um die libusb.dll ist, dann brauchst Du die libusb.dll garnicht in Dein Projekt einzubinden.

Du brauchst dann halt nur (wie Du es ja schon hast) die SharpUSBLib.dll als Projektverweis einzubinden. Allerdings muss die libusb.dll auf Deinem Rechner installiert sein, da die SharpUSBLib.dll intern darauf zugreifen will.

07.03.2006 - 09:59 Uhr

Ob sie registriert sein muss, weiss ich nicht, aber registrieren per Code kannst Du, indem Du regsvr.exe startest (über Process.Start).

06.03.2006 - 12:44 Uhr

@cmpxchg

Leider hat Dein Beispiel nichts mit dem Singleton-Entwurfsmuster zu tun.

Ein Beispiel für das Singleton-Muster sähe z.B. so aus :



public class SingletonDemo
{
  private static SingletonDemo mInstance;

  private SingletonDemo()
  {
  }

  public static SingletonDemo GetInstance()
  {
     if(mInstance == null)
       mInstance = new SingletonDemo();

     return mInstance;
  }

  // ...
  
  //Funktionsdefinitionen
}



Damit ist gewährleistet, dass es zur Laufzeit maximal eine Instance dieser Klasse geben kann. DAS ist das Singleton-Muster. Was Du beschreibst ist aus der Sicht der objektorientierten Programmierung (tut mir leid, dass ich es so sagen muss) Müll.
Das erinnert mich mehr an prozedurale Programmierung, nur dass Du eine Klasse missbrauchst um Prozeduren zu definieren.

Globale Variablen gibt es in C# nicht, Punkt aus basta. Wer globale Variablen (und die damit verbundenen Spaghetti-Code Strukturen) haben will, der soll gefälligst VB6 oder so verwenden.

Und selbst bei Deinem Beispiel sind die Variablen nicht von "überall" aus zugreifbar. Wenn Du in einem Projekt keinen Verweis auf die Assembly hast wo das Zeug drinsteckt kommste auch nicht dran. Mal von Namespaces ganz abgesehen...

Sorry, wollte Dich nicht niedermachen oder angreifen, aber ich hab mich lang genug mit VB6 rumgekloppt und bin froh, dass es endlich eine typsichere und rein objektorientierte Sprache wie C# gibt 🙂

23.02.2006 - 13:04 Uhr

Mach doch einfach 2 icons und wechsle dann in deinem NotifyIcon-Control das Icon hin und her, so wie Du es gerade brauchst. Hab ich hier jedenfalls so gemacht und funzt ohne Probleme...

20.02.2006 - 18:52 Uhr

Hallo zusammen !

Ich wollte mal ein bissel rumspielen mit MDX, und hab dabei angefangen so ein kleines Tile-basiertes Spielchen zu basteln, ähnlich Emerald Mine (für die die es noch aus C64-Zeiten kennen).

Bisher läuft auch alles ganz gut, Clipper Front / Back Buffer Zeichnen funzt bei ganz banalen Beispielen.

Meine Idee war nun, der Tile-Klasse eine Surface als Property zu verpassen, in die die Grafik gezeichnet wird (mittels DirectDraw, DrawFast Methode).

Der Konstruktor der Tile-Klasse sieht dann so aus :


/// <summary>
/// 
/// </summary>
public DXTile(string src, Device device)
{		
	mSurfaceSource = src;
	mDevice = device;
	mSurface = new Surface(src, new SurfaceDescription(), mDevice);
}

Wobei src der Pfad zu der Grafik-Datei ist.

Nun meine Frage : Wenn ich das Spielfeld zeichnen will, kann ich dann in einer Schleife alle Tiles in den Backbuffer (der selbst ein Surface ist) zeichnen ?

Oder würde dabei bei jedem Zeichnen einer neuen Surface, die letzte verschwinden ?

14.02.2006 - 09:59 Uhr

Genauso hatte ich mir das auch gedacht, aber dem ist NICHT so !

Ich hab nochmal etwas weiter rumgetestet :

Beim Marshalling des Bool-Typen auf einen integer (oder einen C#-bool Typ) scheint irgendwas schief zu laufen, denn es steht nachher definitiv NICHT 0 in der Variablen auf C#-Seite, sondern irgend ein zufälliger Wert, der immer zu true ausgewertet wird.

Es klappt wirklich nur, wenn man den bool-Wert auf C# Seite als 1-bit Zahl marshallt (UnamangedType.I1). Ist halt schon ein Stückchen Arbeit, auf so etwas überhaupt mal zu kommen bei der Fehlersuche...

13.02.2006 - 16:18 Uhr

@sheitman

Ist mir schon klar, dass wir hier in einem C# Forum sind, aber das Topic lautet ja hier "Rund um die Programmierung" - und Programmierung ist eben nicht nur C# - ja es gibt noch was anderes als das .NET-Framework auf der Welt 😉

@talla

Das mit dem -1 bei VB 6 war mir zwar bewusst, ich hab da aber noch nie bewusst ein Problem mit gehabt. Wenn ich aus ner stinknormalen C++ DLL einen bool auf VB 6 Seite kriege, behaupte ich mal, das funktioniert ohne Probleme. Dasselbe gilt für C++ -> C#, funktioniert auch problemlos.

Aber die spezielle dll um die es geht ist nun mal eine C-DLL, keine C++ DLL und da scheint es wohl einen Unterschied zu geben.

Ich werd mal nachforschen, was da genau los ist. Denn auch wenn der ANSI C-Bool nur 0 oder 1 sein kann, verstehe ich trotzdem nicht ganz, warum er auf C# Seite immer als true interpretiert wird, selbst wenn der Zahlenwert nach dem Marshalling 0 (also false) ist.

10.02.2006 - 13:12 Uhr

Hallo zusammen !

Ich hab eine C-dll in der eine Funktion drin deklariert ist, die einen bool als Rückgabewert liefert.

Auf C#-Seite bin ich gerade in eine Falle gerannt. Marshallt man die Funktion nämlich so :


[DllImport("MyFuncs.dll")]
public static extern bool CheckState();

dann liefert die Funktion immer true zurück, egal ob auf der C-Seite der return-Wert true oder false war.

Wie ich jetzt herausgefunden habe, liegt das daran, dass der ANSI C bool Typ eine 1-bit Zahl (0 oder 1) ist, das Default-Marshalling von .NET den bool Typ aber als 32-bit Zahl auffasst.

stattdessen muss man auf C#-Seite so marshallen :


[DllImport("MyFuncs.dll")]
[return : MarshalAs(UnmanagedType.I1)]
public static extern bool CheckState();

Meine Frage lautet jetzt : Wie sieht das ganze aus, wenn ich dieselbe C-Funktion auf Visual Basic 6.0 Seite über ein Declare einbinden will ? Muss ich hier auch etwas ähnliches wie ein Marshalling machen, oder kommt VB 6 "instinktiv" mit Ansi C-Typen klar ?

11.01.2006 - 08:34 Uhr

Nicht unbedingt, denn es könnte ja auch den Fall geben, dass man explizit eine Exception haben will, falls niemand ein zu feuerndes Event abonniert hat.

D.h. genau dieser Fall könnte auch ein selbst definierter Fehlerfall sein, und dann macht es Sinn, die Null-Abfrage weg zu lassen.

10.01.2006 - 08:31 Uhr

Man könnte auch die einschlägigen Funktionen aus der Kernel32.dll importieren, also GetPrivateProfileString usw. - und wäre dann in 5 Minuten mit der Klasse fertig und hätte weniger als die Hälfte des Codes.

Wenn man das Rad aber unbedingt neu erfinden will, dann sieht Dein Vorschlag super aus 🙂

10.01.2006 - 08:26 Uhr

Das event ist immer null, wenn niemand es abonniert hat.

Deshalb ist das schon fast zur Grundregel beim Arbeiten mit events geworden, dass man vor dem Abfeuern des events überprüft, ob es überhaupt Empfänger gibt (denn ansonsten macht schon das Feuern keinen Sinn).

Die Überprüfung macht man so, wie es herbivore schon geschrieben hat, eben mit einer Abfrage auf null. Das sollte man grundsätzlich bei allen Events so machen.

05.01.2006 - 11:56 Uhr

Wenn Du hinter das checkThread.Abort() noch ein checkThread.Join() machst, wird es ziemlich wahrscheinlich funktionieren.

Join() sorgt dafür, dass der aufrufende Thread wartet bis der zu Abortende Thread beendet wurde.

05.01.2006 - 09:39 Uhr

Ist "persons" vielleicht ein vordefiniertes SQL-Keyword ? Ich weiss es nicht, aber ich könnts mir vorstellen. Ich hatte sowas mal mit "address" und das hat mich einige Tage gekostet, da drauf zu kommen ...

05.01.2006 - 08:26 Uhr

Ich könnte mir eher vorstellen, dass es Sinn macht, die einzelnen Bilder in einer statischen Variable zu speichern.

Also quasi so eine Art Singleton-Klasse mit private Konstruktor, in dem die Bilder in statische Variablen geladen werden.

Kann es aber nicht belegen ist nur eine intuitive Schätzung meinerseits.

04.01.2006 - 10:17 Uhr

Die Daten können aus einer XML-Datei eingelesen werden mittels

meinDataSet.ReadXML(...)

Genauso kannst Du auch ein gefülltes Dataset in einer XML-Datei abspeichern mittels

meinDataSet.WriteXML(...)

03.01.2006 - 13:13 Uhr

Der Viewer muss aber auch ein Control sein, folglich muss es auch ein Controls.Addd im Viewer geben.

Also quasi :


myViewer.Controls.Add(pictureBox1)

14.12.2005 - 15:31 Uhr

Ok, ich werde es mal versuchen. Danke Euch !

13.12.2005 - 08:54 Uhr

@herbivore

Das Problem ist aber ein anderes...

Beim Versuch eine Hashtable-Property meiner Klasse zu serialisieren, kriege ich eine Exception, die mir sagt, dies ginge nicht da Hashtable das IDictionary Interface implementiert. XmlSerialisierung funzt ja leider nicht mit Interfaces...

Daher meine Frage mal etwas konkreter formuliert :

Hat jemand eine Idee, wie man die Hashtable-Funktionalität in einer eigenen "Wrapper"-Klasse verpacken kann, die dann ohne die Implementierung des IDictionary-Interfaces auskommt ?

z.B. könnte man ja zwei ArrayLists nehmen, in einer speichert man die Keys, in der anderen die Values. Da fehlt dann aber noch die Zuordnung des jeweiligen Keys zum dazugehörigen Value. Also irgendwie so muss das gehen...

Oder kann man das vielleicht schon mit einer geschickten Implementierung der getter / setter des Hashtable-Properties umgehen ? Gibts vielleicht irgend ein XmlAttribute, mit dem man die Hashtable für die XmlSerialisierung mappen kann (ähnlich wie bei der ArrayList mit Array(typeof(MeineKlasse))... ?

12.12.2005 - 23:17 Uhr

Hallo zusammen !

Kann mir jemand sagen wie ich eine Hashtable mit dem XmlSerializer serialisieren/deserialisieren kann ?

Wenn es generell nicht geht, weiss dann jemand einen Workaround ? Ich hab schon daran gedacht eine Wrapper-Klasse um die Hashtable zu basteln, aber ich bin mir nicht sicher wie ich das anfangen soll.

Danke schonmal,
Lynix

24.11.2005 - 13:16 Uhr

Hallo zusammen !

Also ich habe einen Networkstream in den ich ein XML-Serialisiertes Objekt reinschreibe, das auf der Client-Seite in einer xml-Datei gespeichert und danach zum damit Arbeiten deserialisiert wird. Das klappt prinzipiell auch problemlos.

Das Ganze habe ich mit asynchronen Sockets implementiert, da dies aus verschiedenen anderen Gründen notwendig wurde. Wenn ich jetzt das serialisierte Objekt in den Stream schicke und gleichzeitig noch andere Messages über den Stream geschickt werden, habe ich oft das Problem, dass die anderen Messages mitten in die xml-Message geschrieben werden, was dazu führt, dass der Empfänger das Ganze nicht mehr deserialisieren kann.

Mein Workaround sieht derzeit so aus, dass ich nach dem schicken den serialisierten Objektes einfach 10 Sekunden mit Thread.Sleep warte, denn in diese Zeit reicht ungefähr aus um das Objekt in einem Stück zu verschicken und auf der anderen Seite auszulesen.

Ich könnte das Ganze jetzt natürlich auch etwas sauberer synchronisieren, aber ich will eigentlich nicht, dass meine anderen Messages verzögert werden.

Jetzt die eigentliche Frage : Kann ich dem Networkstream irgendwie beibringen, dass er verschiedene Schreibe-Vorgänge auf den Stream sequentiell bearbeitet ?

Also nach dem Motto ich hab eine message AAA und eine BBB

Wenn jetzt beide Messages ungefähr gleichzeitig verschickt werden, will ich verhindern das dabei etwas wie AABBBA rauskommt. Gibt es im Networkstream einen internen Synchronisierungs-Mechanismus, den man dafür nutzen könnte ?

Danke schonmal.
Lynix

24.11.2005 - 12:41 Uhr

Nö, Host B muss nur dieselben Interfaces zur Verfügung stellen wie Host A, dann klappts auch mit den Plugins ... Hat der andere Hosts die Interfaces nicht, dann passt das Plugin ohnehin nicht. Ob diese Interfaces nun in der Host-Assembly oder extern liegen spielt dabei keine Rolle.

24.11.2005 - 11:59 Uhr

Ich habs mal spaßeshalber ausprobiert, aber es gab schon direkt Probleme mit dem Namespace. Der Namespace in der VB.NET Assembly liess sich nicht 1:1 in die aufrufende C# Assembly übernehmen mittels using.

Kann sein, dass ich irgendwas vergessen habe, aber ganz so einfach wie manche behaupten gehts jedenfalls nicht...

24.11.2005 - 11:46 Uhr

Ja und wenn du keine sinnlosen Assemblies haben willst, in denen nix drin steckt, dann mach die Interfaces gleich in die Host-Assembly mit rein, denn da gehören sie eigentlich hin.

23.11.2005 - 10:20 Uhr

Ich mache das hier bei uns in unserer Anwendung genauso, allerdings habe ich auf der Host-Seite interfaces hinterlegt, die von dem jeweiligen Client implementiert werden.

Der Host liefert damit sozusagen "Steckplätze" in die verschiedene Clients reingestöpselt werden können.

Also ich würde auf der Host-Seite ein Interface IClass1 machen, meine Class1 das Teil implementieren lassen und dann sollte es mittels


IClass1 cls = (IClass1)Activator.CreateInstance(...)
cls.myMethod();

problemlos funktionieren.

Ich finde übrigens, das ist ein sehr schöner, objektorientierter Ansatz, da die einzelnen Module sehr stark voneinander entkoppelt, und somit wiederverwendbarer werden.

Grüße und viel Erfolg,
Lynix

Edit : Hab grad nochmal gelesen, kann man davon ausgehen, dass Class1 räumlich von dem Host getrennt ist ? Also z.B. in einer anderen dll steckt oder auf einem anderen Rechner liegt ? Weil nur dann macht mein Vorschlag Sinn. Ansonsten reicht es aus, den Namespace der Class1 in deiner Host-Klasse einzubinden.

18.11.2005 - 10:12 Uhr

Hmm, okay - Enum.GetNames kannte ich nocht nicht, sieht aber einfacher aus als meins 😁

18.11.2005 - 10:10 Uhr

public enum test
{
    A,
    B,
    C
}

public class EnumAusgabe
{
    public EnumAusgabe()
    {
    }

    public void TestInhaltAusgeben()
    {
       Console.WriteLine("Enum Test enthält folgendes :");
       int i = 0;
   
       while((test)i != null)
       {
           Console.WriteLine(((test)i).ToString());
       }
    }
}

So ähnlich müsste es gehen, habs aber nicht getestet...

18.11.2005 - 08:35 Uhr

RegEx ist in meinen Augen ehrlich gesagt der letzte Müll, den sich irgendeiner bei M$ hatte ausdenken können. Sorry wenn ich hier jetzt gegen das Weltbild von jemandem flame (ist mir bewusst, dass das hier jetzt geflame ist), aber RegEx das Attribut "einfach" zu verpassen ist in meinen Augen echt Blödsinn.

Ist natürlich subjektiv, aber statt irgendwelche kryptischen Perl-alike Musterbeschreibungen zu basteln und dann zu hoffen dass man es spätestens nach dem 57. Versuch endlich hinkriegt, bastel ich mir lieber mit den zur Verfügung stehenden String-Methoden selbst das was ich brauche.

Das mag zwar mehr Aufwand sein, aber erstens wird der Code lesbarer und zweitens kann das mit dem Aufwand auch ein Bumerang sein, denn wer hat schon Lust für jede String-Manipulation nochmal im I-Net nachblättern zu müssen wie das jetzt mit den RegEx noch gleich funktioniert hat. Wer sich das jedenfalls langfristig auswendig merken kann, hat wahrscheinlich ansonsten nicht genug Arbeit...

Diese Lib werd ich mir auf jeden Fall mal ansehen, in diesem Sinne, danke für den Link 🙂

17.11.2005 - 14:57 Uhr

Nun kommt das Nächste:

C#-Code:
MyObj = (_Module)Activator.CreateInstance(MyType);

Diese Zeile wirft die Meldung

Zitat:
Value cannot be null.
Parameter name: type

Kann es sein, dass der Konstruktor Deines eQ_ModuleMySQL.ModuleMySQL noch Parameter benötigt ? Die Activator.CreateInstance Methode hat eine Überladung, mit der Du Konstruktor-Parameter übergeben kannst. Eventuell braucht das ModuleMySQL einen Paramter zwingend, und beschwert sich wenn dieser null (=nicht angegeben) ist.

15.11.2005 - 13:17 Uhr

Alternativ könntest Du auch mit Deserialisierung arbeiten. Du hättest dann praktisch einen Pack Startup-xml Datei deiner Applikations-Objekte, die Du über Deserialisierung dann immer wieder nutzen könntest um die Anwendung zu "resetten".

15.11.2005 - 13:12 Uhr

Stimmt, darauf bin ich nicht gekommen. Ich denke das gefällt mir ganz gut 🙂

Danke !

15.11.2005 - 12:49 Uhr

Hallo zusammen !

Ich bin kürzlich auf ein Problem gestoßen, für das es doch sicher eine Art Standard-Lösung gibt :

Ich habe z.B. zwei Überladungen eines Konstruktors, die aber beide dieselbe Parameter-Signatur haben.

Bsp :

public MyLogFile(string path, int lineLength, int columnLength)
public MyLogFile(string path, int lineLength, int traceLevel)

  • an dieser Stelle meckert der Compiler logischerweise... nun hab ich gedacht, egal, mach ich halt aus dem einen einen uint, also

public MyLogFile(string path, int lineLength, uint traceLevel)

  • aber leider auch Pustekuchen... Compiler meckert nun, dass die Überladungen nicht unterschieden werden können...

Bei Methoden würde ich ja nun hingehen und halt mehrere Namen vergeben, bei Konstruktoren hab ich da aber ein Problem... die Reihenfolge der Parameter will ich aus Gründen der Benutzerfreundlichkeit auch nicht verändern (ist ja Schwachsinn bei einem Konstruktor mit 20 Parametern, einmal den filePath an erster Stell, einmal an letzter Stelle und einmal in der Mitte stehen zu haben...

Wie löse ich dieses Problem jetzt ?

Danke !

xml

14.11.2005 - 10:52 Uhr

Oder du synchronisierst das Ganze, wartest aso bis alle Teile der Nachhricht über den Stream empfangen wurden bevor Du mit dem parsen beginnst. So hab ichs gemacht...

10.11.2005 - 08:36 Uhr

Und nochmal ich 🙂

Ich hab noch ein weiteres Problem, denn zwecks langzeit Performance-Test eines Projektes soll die Prozessorauslastung im Fehlerfall ausgelesen und geloggt werden.

Leider hat mir Google auch hier nicht weiter geholfen, ich hab nur bei Codeproject einen Artikel gefunden in dem von der magischen "Microsoft-API" gesprochen wird...

Hat jemand eine Idee, wie ich mit C# (auch gerne über irgendeine native API) an die Angaben des Taskmanagers, insbesondere der Prozessorauslastung rankomme ?

Schonmal danke,
Lynix

10.11.2005 - 08:32 Uhr

Hallo zusammen !

Also ich benutze das VS.NET 2003 (Framework 1.1) und habe mich gefragt, ob es möglich ist, eine universale XMLSerializer Funktion zu schreiben, der ich als Argument ein beliebiges Objekt geben kann, welches dann in Form einer XML-Datei serialisiert wird.

Beim Anlegen des XMLSerializer muss man ja den Typ des Objektes angeben, von daher bin ich derzeit etwas ratlos. Mit Template-Klassen im Framework 2.0 könnte ich mir vorstellen, dass es funktionieren könnte, aber mit dem 1.1er Framework hab ich bisher noch keine Idee und auch bei Google etc. nix gefunden.

Hat von Euch jemand eine Idee ?

Danke,
Lynix

09.11.2005 - 19:38 Uhr

Kann ich nur bestätigen und bin ich auch heute erst reingetappt :

Ich hab ein Form, in dem ein Thread gestartet wird. Nun wird in diesem Thread ein neues Form angezeigt und die ShowInTaskbar Eigenschaft auf false gestellt.

Wenn ich jetzt innerhalb dieses Threads eine Messagebox anzeige, wird beim Schliessen der Messagebox auch das Form geschlossen und man hat keine Möglichkeit mehr, das Form wieder sichtbar zu machen ...

Probiert es aus, lässt sich mit einer Testanwendung in 5 Minuten nachprogrammieren (haben wir auch gemacht weil wir es nicht glauben wollten).

Wir sind mit dem Testen noch nicht ganz fertig, aber es sieht so aus als ob beim Schliessen der Messagebox (modaler Dialog) vom Windows-BS eine Message gesendet wird, die aus irgendeinem Grund auch von dem Formular aufgefangen und abgearbeitet wird.

Das Kuriose ist, wenn man die ShowInTaskbar Property des Forms nicht auf false setzt, funktioniert alles einwandfrei.

Sehr dubios das Ganze ...

09.11.2005 - 10:08 Uhr

Wahrscheinlich ist das Fenster auf Topmost eingestellt. Meine Idee wäre, zu versuchen diese Einstellung mit Hilfe des Fenster-Handles zu ändern, wobei ich mir vorstellen kann, das das sehr auf Low-Level Programmierung hinauslaufen könnte.

09.11.2005 - 10:05 Uhr

Keine Ahnung ob das besser ist als mit Thread.Sleep aber hast Du mal einen Timer mit 5ms Ticks probiert ?

09.11.2005 - 10:01 Uhr

Hallo !

Schau Dir mal das Factory-Muster an.
Definiere auf der Seite der aufrufenden DLL ein Interface für den Typ in der aufgerufenen DLL und implementiere das Interface dann.

Nun kannst Du mit einer Factory problemlos Objekte aus Deiner dynamisch geladenen DLL verwenden. Hier noch etwas Sourcecode zum Denkanstoss :


/// <summary>
		/// Tries to create a new instance of the given type, searching it in the given assembly.
		/// </summary>
		/// <param name="aioType">The name of the instance type, implementing the IAnalogIO interface.</param>
		/// <param name="assembly">The name of the assembly, the type is located in.</param>
		/// <returns>An instance of the given type from within the given assembly.</returns>
		/// <list>
		/// <listheader>
		/// <term>
		/// Possible Exceptions
		/// </term>
		/// </listheader>
		/// <item>
		/// <term>
		/// InitializationException
		/// </term>
		/// <description>
		/// Thrown if the specified type either was not found in the specified assembly or if the given types is an abstract type.
		/// </description>
		/// </item>
		/// </list>
		internal IJoystick CreateJoystick(string joystickType, string assembly)
		{
			Hashtable types = new Hashtable();
			Assembly ass = Assembly.Load(assembly);

			foreach(Type t in ass.GetTypes())
			{
				if(typeof(IJoystick).IsAssignableFrom(t) && !t.IsAbstract)
					types.Add(t.Name, t);
			}

			if(types.Contains(joystickType))
			{
				IJoystick joy = (IJoystick)Activator.CreateInstance((Type)types[joystickType]);	
				return joy;
			}
			else
				throw new InitializationException("Error initializing peripherals : The Joystick-type " + joystickType + " is not defined in Assembly " + assembly + " !!"); 
		}

Welche Typen aus welcher Assembly beim Initialisieren der Anwendung geladen werden sollen kannst Du dann z.B. per Config-File bestimmen.

Vielleicht hilfts ja.

Grüße,
Lynix

05.08.2005 - 10:13 Uhr

Wenn es egal ist, ob die C++ dll managed oder unmanaged ist, dann kannst du in den Projekteigenschaften des C++ Projektes unter Konfigurationseigenschaften -> Allgemein -> Verwaltete Erweiterungen verwenden auf "true" setzen.

Danach kannst Du die C++ dll als Verweis einbinden, so wie Norman es am Anfang des Threads beschrieben hat.

Ist dir das managed/unmanaged nicht egal, dann kommst D nicht drumherum mit DllImport zu schaffen, was aber auch nicht besonders schwierig ist.

Edit : Ups, ich hab nicht gesehen, dass der Thread 2 Seiten hat, sorry...

05.08.2005 - 09:52 Uhr

Also ich weiss jetzt nicht, ob das was mit Deinem Problem zu tun hat (ich glaube eher nicht, aber sicher ist sicher) - Der Typ Long auf VB bzw. C-Seite entspricht dem Typ Int32 oder int auf C# seite.

Von daher würde ich schonmal alle Long-Variablen als int importieren. Ansonsten könnte ich mir vorstellen, dass es etwas mit dem ref byte zu tun hat.

Ich hatte mal ein ähnliches Problem, mit einem ByRef String, den ich versucht habe, als ref string zu importieren. Irgendwann hab ich dann durch Trial & Error herausgefunden, dass der ByRef String bzw. &string dem StringBuilder in C# entspricht.

Also an der Stelle würde ich mal weiter forschen, vielleicht findet sich dazu ja was in der MSDN....

26.07.2005 - 16:41 Uhr

Hi !

Also die Aussage, "wenn es mit VS2003 geschriebenes C++ ist, dann muss es ja managed C++ sein" - ist leider nicht richtig.

Mit dem VS2003 kann man genauso gut auch unmanaged C++ produzieren. Das kann bei dem C++-Projekt in den Projekteigenschaften eingestellt werden (Projekteigenschaften -> Konfigurationseigenschaften -> Allgemein -> Verwaltete Erweiterungen verwenden).

EDIT : Standardmäßig ist ein neu angelegtes C++ - Projekt übrigens "nicht verwaltet", daher empfiehlt es sich, da erstmal die managed extensions zu aktivieren, dann sollte das Einbinden ins C# - Projekt mittels dllimport kein Problem sein...

Umgekehrt ist es übrigens einfacher, C#-Code lässt sich problemlos von C++ aufrufen, allerdings nur wenn Managed Extensions aktiviert sind. Dann nämlich kann man auch bei C++-Projekten ganz normal wie bei C# mit Projektverweisen und #using arbeiten...

19.07.2005 - 15:47 Uhr

Events und Delegates sind Konzepte, die C# zur Verfügung stellt um Ereignis-gesteuerte Programmierung zu ermöglichen.

Ein Ereignis ist im einfachsten Fall z.B. ein Klick des Benutzers auf einen Button. Durch diesen Click wird ein Event abgeschickt, und deine Logikobjekte fangen dieses Event mit einem Delegate auf, der das Event an eine Handlerfunktion weiter "delegiert".

Solche Ereignisse und das dazugehörige Handling wie Buttonclicks etc. werden Dir wenn Du z.B. das Visual Studio zum C#-Programmieren benutzt bereits automatisch vor-realisiert.

Du kannst aber auch eigene Events definieren und somit Deine eigene Logik Ereignisgesteuert programmieren.

So könntest Du z.B. immer dann wenn sich der Wert einer bestimmten Variable ändert, ein Event abschicken, dieses Event in deiner GUI auffangen und per Delegaten an eine Handlerfunktion weiterverweisen, die die Wertveränderung z.B. über ein Label an der Oberfläche anzeigt.

Das Ganze hat Vor- und Nachteile :

Hauptvorteil nach meiner Meinung : Als Programmierer ist man freier, da man nicht sture, sequentielle Abläufe programmieren muss, sondern seine Logik dynamischer gestalten kann.

Hauptnachteil nach meiner Meinung : Durch das häufige Verwenden von Events neigen Schnittstellen oft dazu, unübersichtlich zu werden und für den Benutzer deiner Komponenten wird es schwieriger, da er mehr über die interne Programmierung Deiner Komponente wissen muss, wenn er sie benutzen will.

Also Fazit : Wenn Du etwas mit API-Charakter programmieren möchtest, dann solltest Du Events, wenn überhaupt nur intern verwenden, und nicht nach aussen schicken. Ansonsten erspart ein Event an der richtigen Stelle u.U. einiges an Arbeit.

03.07.2005 - 17:17 Uhr

Hallo zusammen, ich hab hier ein kleines Problemchen, dass ich nicht ganz nachvollziehen kann.

Ich versuche in meiner ASP.NET Webanwendung einen Eintrag in einer Access-Datenbank zu löschen, aber irgendwie gelingt es mir nicht. Neue Einträge hinzufügen klappt, aber das löschen nicht...

ArtikelNummer ist der Primärschlüssel der jeweiligen Zeile, nun lasse ich den Benutzer über ein Formular die ArtikelNummer eingeben, die ich dann verwende um den dazugehörenden Eintrag zu löschen.

Mein Code sieht so aus :



public void DeleteArticle(string articleID)
		{
			mConnection.Open();

			string commandString = "DELETE FROM Artikel WHERE ArtikelNummer = @artNo";

			OleDbCommand command = new OleDbCommand(commandString, mConnection);
			OleDbParameter artNo = new OleDbParameter("artNo", OleDbType.Integer, 1000, "ArtikelNummer");
			artNo.Value = Int32.Parse(articleID);
			command.Parameters.Add(artNo);
			command.ExecuteNonQuery();

			mConnection.Close();
		}


Leider funktioniert das nicht, es kommt auch keine Fehlermeldeung, aber wenn ich anschliessend in die Datnebank reingucke, ist der entsprechende Eintrag nicht gelöscht worden.

Muss ich wenn ich den Primärschlüssel verwenden möchte irgendetwas anders machen als sonst ?

Danke für Eure Hilfe !