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

22.05.2006 - 09:21 Uhr

Du brauchst NICHT unbedingt eine statische Referenz (Projektverweis). Stattdessen kannst Du mal hier im Forum oder in der MSDN unter Assembly.Load() bzw. Activator.CreateInstance gucken.

Viel Glück,
Lynix

19.05.2006 - 16:18 Uhr

Eine oft verwendete, aber wie ich finde unschöne da mit viel Verwaltungsaufwand verbundene Möglichkeit ist das Verwenden von Callback-Methoden (in C# Delegates).

Ich hab das Projekt, an dem ich gerade arbeite Sternförmig aufgebaut : In der Mitte steht ein Logik-Kernel, der mit der UI kommuniziert (beidseitig), die einzelnen Plugins, die hier verschiedene Hardwarekomponenten sind, greifen von sich aus auf den Kernel zu, wobei der Kernel nur ein Interface kennt.

Also der Kernel gibt z.B. über die Definition eines Interfaces vor : Ich will Geräte vom Typ DigitalIO-Karte benutzen können. Ab diesem Zeitpunkt können alle Geräte, die das DigitalIO-Interface des Kernels implementieren können, als austauschbare Plugins eingebunden werden.

Der Nachteil daran ist natürlich, dass die einzelnen Plugins nur noch in Verbindung mit diesem Kernel benutzt werden können. Ich koppele Quasi die Plugins an die Hauptanwendung und nicht umgekehrt, wie es der Threadstarter angedeutet hat.

17.05.2006 - 12:10 Uhr

Hallo !

Hier eine Funktion, die ich mir mal geschrieben habe um eingebettete Icons auszulesen. Die sollte sich entsprechend anpassen lassen um auch xml-Dateien oder sonstwas zu lesen :


/// <summary>
		/// 
		/// </summary>
		/// <param name="sourceAssembly">The source assembly, where the icon has been compiled to.</param>
		/// <param name="iconName">The name of the icon file without file extension.</param>
		/// <returns>The requested icon. Returns null if the icon wasn't found in the sourceAssembly.</returns>
		public static Icon GetEmbeddedIcon(Assembly sourceAssembly, string iconName)
		{
			Icon retVal = null;
			string[] resources = sourceAssembly.GetManifestResourceNames();

			for(int i=0; i<resources.Length; i++)
			{
				if(resources[i].IndexOf(iconName + ".ico") >= 0)
				{
					retVal = new Icon(sourceAssembly.GetManifestResourceStream(resources[i]));
					break;
				}
			}

			return retVal;
		}

15.05.2006 - 16:37 Uhr

Hallo PyroTechnics,

soweit ich weiss kommt das Click-Event vor dem MouseUp Event. Das bedeutet, Du fragst im Click-Event ab ob der Focus auf einer der Textboxen liegt, was zu diesem Zeitpunkt noch nicht der Fall ist, da der Focus durch das Clicken auf dem Button liegt.

Der MouseUp Event, in dem Du den Focus auf eine Textbox legst kommt erst nach dem Click (also nach Deiner Überprüfung).

Kannst ja mal probieren anstatt in dem MouseUp-Event im MouseDown-Event deinen Focus zu setzen.

P.S.:

Mir fällt gerade noch auf, dass Du beim MosueUp der Textbox den Focus setzt. Ich schätze mal du willst aber, dass der Focus auf die Textbox gesetzt wird, wenn der Button gedrückt wird oder ? Ansonsten hab ich Dich vielleicht falsch verstanden ...

15.05.2006 - 16:30 Uhr

Hallo DjBepy, was machst Du denn in der Funktion Machwas() ? Hast Du in deinem Haupt-Thread irgendwo versehentlich eine Endlos-Schleife fabriziert ?

@norman_timo

Ich habs mir grad mal angesehen, sieht ja vom Prinzip her genauso aus wie meine Klasse, nur, dass dort schon eine Warte-Schleife in der Thread Methode vorgegeben ist. Ist also eher so eine "permanenter Workerthread" - Klasse. In meiner Klasse oben kann man dagegen selbst in der Methode auf die das ThreadDelegate zeigt entscheiden was man macht (einmalige Ausführung oder Schleife).

15.05.2006 - 08:43 Uhr

Da sich ein nicht statischer Delegat immer auf ein Objekt bezieht, kann man dieses als Parameter verwenden.

Das würde mich jetzt aber mal interessieren. Hast Du ein Beispiel dafür für .NET 1.1 ? Denn über das Problem haben wir uns hier in der Abteilung schon mächtig den Kopf zermartert ohne eine Lösung (ausser der Klasse oben) zu finden. Wenn das einfacher geht dann bitte her damit 🙂

12.05.2006 - 16:15 Uhr

Ich habs jetzt mal sehr grundlegend auf die Schnelle mit Kommentaren versehen. Eine letzte Sache noch, um den Thread nun zu starten musst Du das Ganze wie folgt aufrufen :


string meinString = "Dies ist der String, den ich an meinen Thread übergeben will";
MyThread t = new MyThread(meinString, new ThreadDelegate(Machwas));
t.Start();

Eine Besipielfunktion die man dem Thread übergeben könnte :


public void Machwas(object parameters)
{
string meinString = (string)parameters;
//ich mache was mit dem String;
}

12.05.2006 - 15:55 Uhr

Wie gesagt, die Klasse oben, ist mit Sicherheit alles Andere als Wasserdicht, daher würd ich ohnehin nicht empfehlen, die so wie sie ist zu verwenden. Du kannst es nur als Basis nehmen um sozusagen "auf die richtige Spur" zu kommen 🙂

Also das Ganze funktioniert so weit wie ich es bisher gebraucht habe schon, aber ich übernehme keinerlei Garantien für den obigen Code 🙂

Was genau an dem Code macht Dir denn Probleme ? Frag doch mal etwas konkreter.

12.05.2006 - 15:29 Uhr

Der System.Threading.Thread kann leider nur auf eine parameterlose Funktion zeigen. Da man wohl aber auch mal parameter an eine Thread-Funktion übergeben will (was ja nix magisches ist, und womit z.B. Java keine Probleme hat) hab ich mir wie so oft was Eigenes gebastelt, als Workaround um dieses Standardproblem quasi.

Hier mal meine Thread-Klasse :


namespace Helpers.Threading
{
	#region MyThread
	/// <summary>
	/// Zusammenfassung für MyThread.
	/// </summary>
	public class MyThread
	{
                //Der System.Thread, welcher intern verwaltet wird.
		private Thread mThread;
                //Member für die Übergabeparameter aus dem aufrufenden Thread.
		private object mParameters;
                //Das Delegate zeigt auf die Funktion, die der neue Thread ausführen soll. 
		private ThreadDelegate mThreadFunction;
                //Statisches event, welches gefeuert wird, falls innerhalb des Threads eine Exception ausgelöst wird. Dies ist ein weiteres Workaround, da .NET nicht in der Lage ist, Exception, die innerhalb eines Threads stattfinden, zu melden.
		public static event ThreadExceptionDelegate ThreadException;
                //Ein weiteres event, welches gefeurt wird, kurz bevor der Thread (regulär) beendet wird.
		public static event ThreadFinishedDelegate ThreadFinished;

		#region Constructors
                //von aussen wird ein Delegate auf die Zielfunktion, sowie die Parameterliste übergeben.
		public MyThread(object threadParameters, ThreadDelegate threadFunction)						
		{			
	                //der interne System.Thread (der nur parameterlose delegates akzeptiert) wird initialisiert.
			mThread = new Thread(new ThreadStart(Run));
                        //die Parameter von aussen werden in den Member-Variablen gespeichert.
			mThreadFunction = threadFunction;
			mParameters = threadParameters;
		}

		public MyThread(object threadParameters, ThreadDelegate threadFunction, string threadID)						
			: this(threadParameters, threadFunction)
		{				
			mThread.Name = threadID.ToString();
		}
		#endregion

                //Folgende Methoden leiten einfach die Aufrufe an die entsprechenden Methoden aus dem System.Thread weiter.
		#region Methods
		public void Start()
		{
			mThread.Start();
		}

		public void Abort()
		{
			mThread.Abort();
		}

		public void Join()
		{
			mThread.Join();
		}

		public void Join(int milliseconds)
		{
			mThread.Join(milliseconds);			
		}

		public void Suspend()
		{
			mThread.Suspend();
		}

		public void Resume()
		{
			mThread.Resume();
		}

                //Die Run-Methode bildet quasi das parameterlose Delegate des System.Thread auf unser von aussen übergebenes Delegate ab. Der System.Thread, der nur parameterlose Methoden aufrufen kann, ruft diese Run-Methode auf, welche dann intern unser Delegate feuert (dem dann die eigentlichen Parameter übergeben werden können).
		private void Run()
		{
			try
			{
				mThreadFunction(mParameters);

				if(ThreadFinished != null)
					ThreadFinished(mThread.Name);
			}
			catch(Exception ex)
			{
				if(ThreadException != null)
					ThreadException(mThread.Name, ex);
			}
		}
		#endregion
	}
	#endregion

	#region Delegates

	public delegate void ThreadExceptionDelegate(string threadID, Exception ex);
	public delegate void ThreadFinishedDelegate(string threadID);
	public delegate void ThreadDelegate(object threadParameters);
	#endregion
}

Eigentlich hatte ich ursprünglich von Thread erben wollen, um dann festzustellen, dass die Klasse sealed ist. Das obige Beispiel funktioniert bei mir problemlos, ich kann meinem Thread ein Funktionsdelegate übergeben, welches auf eine Funktion, die als Parameter ein Object erwartet, zeigt. Du kannst das natürlich beliebig abändern (brauchst nur das ThreadDelegate zu ändern) wenn Du was anderes als ein Object übergeben willst.

P.S.: Sorry, dass der Code nicht dokumentiert ist, ich sehe es als Quick & Dirty Lösung für ein Standardproblem an, zu dem es im .NET Framework leider keine vernünftige Lösung gibt, daher hab ich mir bisher auch nicht die Mühe gemacht. Sollte aber relativ einfach anchvollziehbar sein, ansonsten frag einfach nochmal.

Ich hoffe es hilft 🙂

Edit : Sehr grundlegende Kommentare hinzugefügt

12.05.2006 - 15:21 Uhr

Dann musst Du in die Warteschleife noch Application.DoEvents() einfügen. Application steckt in Namespace System.Windows.Forms.

12.05.2006 - 08:34 Uhr

hallo dArignac,

du könntest den Worker-Thread in einer Endlosschleife laufen lassen :


private void ThreadMethode()
{
   //hierhin die Aktion, die ausgeführt werden soll (EventListener initialisieren)

   while(!ThreadFinished)
   {
      Thread.Sleep(10);
   }
}

Um den Thread dann zu beenden kannst Du eine Funktion aufrufen, die ThreadFinished auf true setzt.

10.05.2006 - 19:26 Uhr

Jo es ist schon klar, dass man es irgendwie tricksen kann, dass es funktioniert, das hab ich schon 🙂

Und trotzdem find ich es schwachsinning ein solches keyword mit dieser Funktionalität dann überhaupt einzuführen. Mit OOP hat das null und nix zu tun. Aber egal, man muss sich an solche Sachen halt gewöhnen wenn man mit .NET arbeitet.

Vielen dank jedenfalls nochmal, ich kenne ja jetzt den Workaround für das Problem und hab die Bestätigung bekommen, dass der Fehler nicht bei mir liegt 🙂

10.05.2006 - 19:19 Uhr

@Traumzauberbaum

Richtig ! Die Betonung muss aber auf IMMER liegen. Bei Methoden, Konstruktoren, Properties etc. kann die Basisklasse entscheiden ob sie den abgeleiteten Klassen Zugriff gewähren will oder nicht, bei Events haben abgeleitete Klassen nie Zugriff. Und genau an diesem Punkt frage ich mich was das eigentlich für einen Sinn macht ?

10.05.2006 - 19:14 Uhr

nein, da liegst du falsch. Etwas kann vererbt werden, aber das heißt ja nicht, dass man in der Unterklasse (direken) Zugriff darauf hat. Bei jedem privaten Member ist das so. Und der Delegat einen Events ist eben private. Also ist alles schlüssig und im Einklang mit allen objektorientierten Konzepten.

Das sehe ich anders, denn bei jedem privaten Member oder Methode kann man über den Spezifizierer angeben, ob die abgeleitete Klasse Zugriff darauf haben soll, warum also nicht bei einem Event ? Wenn ich das Event nicht nach aussen (sprich z.B. abgeleitete Klasse) freigeben will, kann ich es ja auch private deklarieren.

Ich könnte das Ganze ja noch bei static events verstehen, da es dort einen gewissen Sinn machen würde, diese genau auf den jeweiligen Typ zu beziehen in denen sie deklariert sind, aber bei Instanzen-Events kann ich das echt nicht nachvollziehen.

10.05.2006 - 19:09 Uhr

Noch ein Kommentar @Traumzauberbaum

Das hat einfach den Grund, dass man ja nicht immer will, dass eine abgeleitete Klasse das Event auslösen kann. Beispielsweise wenn man von Form ableitet.

Sorry, aber ich bin der Meinung, wenn man nicht will, dass die abgeleitete Klasse all das kann was die Basisklasse kann, dann darf man nicht davon ableiten, bzw. hat einen Fehler im Klassenkonzept. In dem Fall muss man seine Basisklasse wohl eher weiter aufteilen.

10.05.2006 - 19:04 Uhr

Vielen Dank an alle für die Erläuterungen. Mein Fazit heisst : Ich gebe SUN ganz klar recht 🙂

Wenn die Basisklasse ein Event feuern kann (Funktionalität) muss die abgeleitete Klasse das genauso können, ansonsten hat das nichts mehr mit Vererbung zu tun. Vielleicht muss man das dann MS-Vererbung oder Vererbung.NET nennen g

10.05.2006 - 16:51 Uhr

Hallo zusammen !

Ich bin heute auf ein (wie ich finde) merkwürdiges Verhalten gestossen:

Ich habe eine Basis-Klasse Sensor von mehrere weitere Klassen abgeleitet sind. In der Basisklasse gibt es ein public event, welches ich innerhalb der abgeleiteten Klasse feuern wollte, falls ein bestimmter Zustand festgestellt wurde.

Leider lässt mich der Compiler das nicht tun. Stattdessen erhalte ich die Fehlermeldung :

BaseClasses\Laser.cs(69): Das Ereignis 'Sensor.Result' kann nur auf der linken Seite von += oder -= stehen (es sei denn, es wird innerhalb des Typs 'Sensor' verwendet).

Das muss aber doch funktionieren oder ? Wenn ich in der Basisklasse das event feuern kann, muss das Event doch auch in der abgeleiteten Klasse gefeuert werden können. Ansonsten würde doch der abgeleiteten Klasse ein Teil der Funktionalität der Basisklasse fehlen ?

Für eine Erläuterung warum das so ist wie es ist und was ich machen muss um das so hinzukriegen, wäre ich sehr dankbar.

05.05.2006 - 15:29 Uhr

Naja, mit der Zeit sollte man in diesem Forum auch mal gelernt haben, dass von gewissen Leuten generell erstmal Hilfe wie "such mal bei Google" kommt. Wenn ich gewisse Benutzernamen in einem Thread sehe, überspring ich mittlerweile schon instinktiv die Beiträge dieser Benutzer. Früher war das hier im Forum auch mal anders, aber mittlerweile ist man wohl etabliert genug, dass man meint es nicht mehr nötig zu haben, Fragen anständig zu beantworten. In dem Fall wärs mir persönlich aber immer noch lieber, wenn einfach gar keine Antwort kommt (frei nach dem Motto : Wenn man keine Ahnung hat einfach mal die F***** halten) anstatt solche tollen Kommentare wie "Guck doch mal bei Google".

Aber naja, ist nur meine Meinung, und es gibt ja auch genügend andere Foren mittlerweile.

03.05.2006 - 13:19 Uhr

so vielleicht :



bool[] z1 = new bool[] {true, false};
bool[] z2 = new bool[] {true, false};

for(int i=0; i<z1.Length; i++)
{
   for(int j=0; j<z2.Length; j++)
   {
      System.Console.Write(z1[i].ToString() + " " + z2[j].ToString() + " " + (z1[i] && z2[j]).ToString()); 
   }
}


Das wär jetzt nur das Beispiel für den &&-Fall.

02.05.2006 - 13:02 Uhr

Am liebsten wäre es mir, wenn ich die Namen garnicht kennen müsste, ich weiss nur an welcher Stelle welche Kategorie steht. Also meine Funktion A soll immer die 3. Spalte der Tabelle lesen, meine Funktion immer die 6. Spalte usw. Die Namen der Spalten sollen dabei möglichst keine Rolle spielen.

Bei den Datenspalten wäre es mir zur Not noch egal, wenn die Namen fest sein müssten, aber besonders bei den PrimaryKeys will ich einfach, dass er den benutzen kann um eine spezielle Zeile zu finden, ohne dass ich dazu wissen muss, wie die Spalte, in der der PrimaryKey steht heisst.

02.05.2006 - 10:22 Uhr

Danke schonmal für die Antworten !

Das Problem ist, dass ich gerade unabhängig vom Namen der Primary-Key Spalte bleiben will. D.h. irgendwann könnten Tabellen hinzukommen, die nicht von mir sind und ich würde nur ungern die Namensvergabe beim erstellen eigener Tabellen einschränken.

Daher geh ich halt davon aus, dass ich weder zur Laufzeit noch zur Designzeit die Namen der Spalten kenne.

02.05.2006 - 10:12 Uhr

Hallo !

Wenn ich mich nicht täusche, ist es nicht möglich, komplette C++ Klassen direkt auf C# Seite zu marshallen. Gemarshallte Structs hab ich schon gesehen, aber das allein sah schon sehr kompliziert aus. Da Klassen komplexer sind als Strukturen, wird das wohl so nichts werden.

Ich würde Dir, wie svenson es auch schon geschrieben hat, auch dazu raten, zumindest für deine Windows-Version einen managed C++ Wrapper um deine C++ dll zu bauen und diesen dann auf C# Seite einzubinden.

Falls Deine C++ dll eine COM-Komponente ist, gibt es auch noch die Möglichkeit, die dll einfach als Projektverweis in dein C# Projekt einzubinden. Das Visual Studio erstellt dann automatisch einen Com+ Wrapper, den Du als ganz normale .NET-Assembly verwenden kannst.

Ich hoffe damit kommst Du irgendwie weiter.

02.05.2006 - 10:06 Uhr

Stichwort : Überladung

27.04.2006 - 21:06 Uhr

Vielleicht sollte ich noch dazu schreiben, was ich machen will - eventuell gibts ja dazu auch eine andere Lösung.

Also ich hab in meinem privaten Hobby-Webprojekt eine Access2003-Datenbank mit mehreren Tabellen.

Wie sich das so gehört hab ich in jeder Tabelle einen Primärschlüssel angelegt. Diese Primärschlüssel-Spalte heisst nun aber in jeder Tabelle anders, da dies einfach der Übersichtlichkeit dient...

Ich versuche nun eine Funktion in meiner Datenbank-Klasse zu schreiben, und zwar eine bool EditRow(string tableName, DataRow row, int primaryKey).

Die Funktion soll die entsprechende Zeile (die zum angegebenen primaryKey gehört) in der angegebenen Tabelle durch die angegebene DataRow ersetzen.

Da ich nun um das Dataset zu kriegen, mit dem ich später das Update machen möchte, nicht die komplette Tabelle auslesen möchte (also quasi SELECT * FROM tableName), sondern in diesem Dataset nur genau die Zeile drin haben will, die geändert werden soll, frage ich mich nun wie ich da anhand des PrimärKeys genau auf die Zeile komme ?

Was ich bräuchte wäre sowas wie SELECT * FROM tableName WHERE PrimaryKey = primaryKey (achtung Pseudo-Code).

Leider hab ich keine Ahnung wie ich das in SQL formulieren soll. Oder bin ich ganz auf dem falschen Dampfer und es gibt eine viel einfache Möglichkeit um genau mein Problem zu lösen ? Ich könnt mir immerhin vorstellen, das sowas ne Standard-Funktionalität ist...

Tausend Dank für Eure Hilfe !

27.04.2006 - 20:51 Uhr

Hallo zusammen !

Mal ne Frage : Gibt es eine Möglichkeit mittels ADO.NET im SQL-String eine Spezielle Spalte anzusprechen durch angabe des Index ?

Also was ich haben möchte wär sowas wie "SELECT * FROM TABLE WHERE COLUMN[0] = 4711" ...

Geht das oder muss ich den Namen der Spalze genau angeben ?

Danke schonmal !

27.04.2006 - 10:14 Uhr

Strings sind Referenztypen ? Sicher ? Ich dachte, die Standard-Typen im Framework, also Int16 / Int32 / Int64 / Double / String usw. wären nichts anderes als Strukturen ?

24.04.2006 - 09:27 Uhr

Ist aber schon ziemlich ineffizient, das so zu implementieren. Immerhin brauchst Du so zwei Schleifen. Ich würde dann auch eher zu einer for-Schleife raten...

22.04.2006 - 01:33 Uhr

Der Unterschied zwischen Managed und Unmanaged liegt doch nur darin, dass dem unmanaged Code ein managed Wrapper fehlt 🙂

21.04.2006 - 14:45 Uhr

Ausserdem muss die Collection die IEnumerable Schnittstelle implementieren, ansonsten kannst Du nicht mit foreach darüber laufen !

21.04.2006 - 14:39 Uhr

Hier ist ein Besipiel aus meinem Projekt :


internal IDigitalIO CreateDigitalIODevice(string dioType, string digitalIOName, string assembly)
{
	Hashtable types = new Hashtable();
	Assembly ass = Assembly.Load(assembly);

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

	if(types.Contains(dioType))
	{
		IDigitalIO dio =
			(IDigitalIO)Activator.CreateInstance((Type)types[dioType], new object[] {digitalIOName});

		return dio;
	}
	else
		throw new InitializationException("Error initializing peripherals : The DigitalIO-type " + dioType + " is not defined in Assembly " + assembly + " !!"); 
}

21.04.2006 - 08:25 Uhr

Mach das Ganze doch über eine Factory, also mit Activator.GetInstance() - das ist m.E. nach der einzige vernünftige Weg um dynamisch zu linken in C#

21.04.2006 - 08:24 Uhr

Mit C++ über ConIO vielleicht. Keine Ahnung ob es da eine Möglichkeit gibt auf C#-Seite...

07.04.2006 - 16:34 Uhr

Naja aus der Warte der OOP gesehen könnte er schon eine "Funktions und Property" - Klasse bauen, die dann von der benutzenden Klasse aggregiert .. oder besser komponiert wird.

Sinn macht das zwar keinen, aber es wiederspricht auch nicht grundsätzlich der OOP. Ob ich jetzt die Eigenschaft "Gewicht" der Klasse Kiste direkt zuordne, oder ob ich die Eigenschaft "Gewicht" der Klasse Kisteninhalt zuordne und dann sage, eine Instanz der Klasse Kiste aggregiert eine Instanz der Klasse Kisteninhalt - ist eigentlich gehopst wie gesprungen... Wenn ich mich nicht täusche läuft das Beschriebene sogar ziemlich auf das Strategy-Pattern heraus.

06.04.2006 - 13:29 Uhr

Das stimmt schon, das streite ich auch garnicht ab. Das Problem ist aber, dass es in der Regel kaum möglich ist immer schon vorher zu wissen an welchen Stellen Exceptions auftreten können.

Das Problem ist, dass man nicht mitgeteilt kriegt, dass überhaupt eine Exception in dem jeweiligen Thread aufgetreten ist. Der Thread stirbt dann einfach, ohne dass man die Chance hat in seinem Hauptthread darauf reagieren zu können. Für den Benutzer sieht es nach wie vor aus, als wär alles in Ordnung.

Wenn der gestorbene Thread aber nun z.B. dafür sorgen sollte dass irgendwo eine Variable mit Daten gefüllt wird, und der Hauptthread irgendwann an die Stelle kommt, wo er auf diese Daten zugreifen möchte, dann nippelt plötzlich die gesamte Anwendung ab, und das u. U. 10 Minuten nachdem der Thread gestorben ist.

Oder ein noch schlimmeres Szenario aus eigener Erfahrung :

Plötzlich stimmen Messwerte nicht mehr, da zur Umrechnung der durch die Hardware gemessenen Werte gewisse Daten-Variablen benötigt werden. Diese Daten-Variablen werden von einem Thread in regelmäßigen Abständen aktualisiert. Stirbt der Thread nun, ohne das man etwas davon merkt, erhält man falsche Werte, die in der Regel nicht soo falsch sind, dass man den Unterschied auf Anhieb bemerkt (weil ja noch die alten Werte in den Datenvariablen stehen).

Einen solchen Fehler sucht man dann schonmal 2 Monate und wenn man ihn gefunden hat, fragt man sich warum nicht einfach eine Mitteilung auf dem Bildschirm angezeigt wird, genauso als wenn die Exception im Hauptthread aufgetreten wäre....

06.04.2006 - 13:18 Uhr

Läuft der gepostete Code in einem eigenen Thread ? Falls ja, kann es sein, dass eine Exception auftritt, über die man dann von .NET nicht informiert wird. Ist nur so eine Idee...

06.04.2006 - 13:15 Uhr

Bei 100 Leuten, die gleichzeitig darauf zugreifen können sollen, kann ich bei Remoting nur sagen : Gute Nacht. Es sei denn die Anforderung erlaubt es, dass die 100 Leute jeweils vielleicht 10 Minuten warten müssen, bis sie die angeforderten Daten kriegen.

Ein Webservice ist übrigens noch langsamer.

06.04.2006 - 13:11 Uhr

Auch wenn Herbivore das wahrscheinlich völlig anders sehen wird, würde ich komplett von .NET Remoting abraten. Wenn die Objekte die hin und her geschickt werden etwas komplizierter als im MSDN-Beispiel werden, gibts damit nix als Probleme, sowohl was die Performance als auch die Stabilität angeht. Wenn Du versuchst Events über die Remoting-Schnittstelle zu schicken, wirds dann richtig haarig.

Obs für Dich in Frage kommt weiss ich nicht, aber ich hab mir einen C#-Wrapper für eine kostenlose C++ Netzwerk API geschrieben, und damit hab ich keine Probleme mehr. Kostet zwar auch etwas Nerven um das Marshalling hin zu kriegen, aber danach läufts schnell und zuverlässig.

Die API heisst RakNet - sollte über google zu finden sein.

Falls das für Dich nicht in Frage kommt, würde ich empfehlen, direkt über Sockets zu programmieren, da hast Du wenigstens mehr Möglichkeiten um verschiedene Anforderungen individuell zu realisieren. Bei Remoting kommst Du irgendwann an den Punkt wo es einfach heisst "geht nicht" und dann stehst Du im Regen.

Viel Glück auf jeden Fall !

06.04.2006 - 13:03 Uhr

Hallo schnurzli,

es gibt eine Methode in einer Windows-API dll (ich glaube es ist die kernel32.dll, aber auswendig weiss ich es grad auch nicht), die Methode heisst jedenfalls CreateFile.

Die kannst Du benutzen um den seriellen Port quasi als "File" zu öffnen. Da kannst dann ganz normal reinschreiben oder draus lesen.

Such einfach mal bei Codeproject, da gibt es einen Artikel dazu, der erklärt wie man genau auf dieser Methode aufbauend von .NET aus auf die RS232 Schnittstelle kommt.

Das .NET Framework selbst bietet leider keinen direkten Zugang, da man das neuerdings bei Microsoft wohl als Sicherheitsrisiko einstuft.

06.04.2006 - 12:59 Uhr

Hallo Zero_Base,

da der Parameter, der "As Any" deklariert ist mit einem kleinen "p" am Anfang beginnt, würde ich drauf tippen, dass es ein Pointer ist. Von daher würd ich zuerst Mal IntPtr versuchen. Im Endeffekt ist das aber Glückssache obs funktioniert - fürs Marshalling gibts leider meist nur Beispiele auf dem "Hello World" - Level in der MSDN...

06.04.2006 - 10:09 Uhr

@herbivore

Das Beispiel aus der MSDN haben wir ausprobiert, funktioniert aber leider nicht...
Das einzige was man machen kann ist über AppDomain.UnhandledException irgendwie zu reagieren, wobei man dort keine Chance hat an das Exception-Objekt dran zu kommen. D.h. man kriegt mit etwas Trickserei mit, dass irgendwo irgendwas schief gelaufen ist, was leider nicht sehr hilfreich ist.

Bei .NET 2.0 ist es sogar noch schlimmer : Da schmiert die Anwendung immer ab mit einer unbehandelten Ausnahme, und man hat generell keine Chance die Ausnahme zu fangen.

Aber ich weiss schon, stimmt alles eh net, und ich soll mir ein Buch kaufen.

06.04.2006 - 09:27 Uhr

Das ist wirklich argumentativ, Respekt.

Ich frage mich ob Du es immer noch für Schwachsinn hältst, wenn Du selbst in meiner Situation wärst. Im Endeffekt darf ich jetzt vorschlagen, die bisherige Arbeit wegzuwerfen und von vorne zu beginnen. Tolle Sache ...

06.04.2006 - 09:19 Uhr

Du solltest Dir auch bewusst sein, dass Du keine Exceptions mehr behandeln kannst wenn Du Multithreading benutzt. Zumindest ist das in .NET Version 1.1 der Fall - Die Exceptions werden nur im Debug-Modus in der IDE geworfen.

Lässt Du das Ganze im Release-Modus laufen, und in einem von Dir gestarteten Thread tritt eine Exception auf, dann stirbt der Thread einfach, ohne dass man als Anwender irgendwas davon merkt. Das führt dann zu unerklärlichen Fehlern an anderen Stellen, die je nach Timing auch immer an anderen Stellen auftreten.

Ich wollte das nur mal in den Raum werfen, vielleicht musst Du dann wenn es so weit ist nicht 2 Monate suchen um darauf zu kommen...

06.04.2006 - 09:08 Uhr

@herbivore

Ich meine nur, dass es mich langsam nervt, dass viele "Features" die als großer Vorteil von .NET auf Präsentationen immer wieder hochgelobt werden, im Endeffekt in der Praxis nicht anwendbar sind. Vielleicht klappt die Serialisierung mit einer bestimmten XY-Anwendung, die zwei Integers und einen String serialisieren muss (zumindest bekomme ich den Eindruck wenn ich mir die Komplexität der Beispiele aus der MSDN anschaue) - aber bei einer komplexeren Geschäfts-Anwendung versagt das Ganze dann kläglichst, aus für mich nicht nachvollziehbaren Gründen.

Dass das Ganze in .NET 2.0 angeblich behoben wurde (wers glaubt ...) nützt mir leider auch nicht viel, da ich hier in der Firma nicht mal so eben mitten im Projekt entscheiden kann, auf .NET 2.0 umzusteigen. Mal ganz davon abgesehen, dass es nicht absehbar wäre, welche neuen Bugs wir uns damit einschleppen würden.

Ich hab das Gefühl, dass dieses ganze .NET vielleicht in 5-10 Jahren halbwegs einsetzbar ist, aber momentan kommt die Benutzung einem Himmelfahrtskommando gleich - immerhin muss man sich ständig gegenüber Kollegen rechtfertigen, wenn man sich für .NET entschieden hat, und solche Fehler die an allen Ecken und Enden lauern, tragen nicht gerade zur Argumentation für .NET bei...

06.04.2006 - 08:34 Uhr

Hilft mir leider nicht weiter (ich nutze .NET 1.1) ...

Naja da bleibt mir wohl nix übrig als Binary Serialization sein zu lassen und wieder auf Ini-Files umzusteigen. Xml-Serialisierung funktioniert ja auch nicht, da 99 % der Typen damit nicht serialisiert werden können 🙁

Hätt ich doch nur C++ genommen ...

Trotzdem danke

05.04.2006 - 14:01 Uhr

Wie man die Versionen fest macht, weiss ich, aber das ist ja keine wirkliche Lösung für das Problem...

Wenn der Benutzer irgendwann mal ein Versions-Update kriegt, dann will er ja uch nicht, weil irgendwo ein bool dazugekommen ist, das komplette Datagrid wieder neu von Hand eintippen müssen. Es muss doch irgendwie möglich sein, Versionskonflikte zu ignorieren und dazugekommene Members mit einem Defaultwert zu setzen oder ?

Wenn ich mittels Reflection eine Instanz mit Dem Activator erzeuge, geht das doch auch. Wenn es keinen passenden Konstruktor zu dem CreateInstance-Aufruft gibt, nimmt er einfach den Konstruktor der am ehesten hinkommt... ich versteh nicht warum er dann bei der Binary-Serialization so kleinlich ist...

05.04.2006 - 13:13 Uhr

Hallo !

Hilft mir leider nicht, da sich das Kapitel nur auf .NET 2.0 bezieht ...

05.04.2006 - 12:10 Uhr

Hallo zusammen, ich hab folgendes Problem mit der Binary Serialisierung.

Wenn ich eine Klasseninstanz serialisiert habe, anschliessend das Projekt neu übersetze und dann wieder deserialisieren will, erhalte ich die Fehlermeldung, dass die Assembly, in der das serialisierte Objekt definiert ist, nicht gefunden werden konnte.

Ich hab über den Debugger mal die inner Exception angeschaut, und es sieht so aus, als ob die dll schon da ist, aber eben durch das Rebuild eine andere Versionsnummer (Buildnummer) hat.

Die Klasse der serialisierten Instanz hat sich aber nicht geändert, d.h. beim Neu Erstellen der Projektmappe wurde quasi eine neue dll erstellt, die von der Funktionalität her unverändert ist, aber leider eine andere Versionsnummer hat.

Kann ich dagegen irgendwas tun ? So nach dem Motto, sage dem BinaryFormatter, dass die Versionsnummer wurscht ist ?

Ich serialisiere ein Usercontrol, in dem ein Datagrid drinsteckt, und ich hab keine Lust, das Datagrid jedes Mal wieder neu füllen zu müssen, wenn ich mal einen Rebuild gemacht habe ... Hilfe !

04.04.2006 - 13:12 Uhr

Jep, es funktioniert nicht, da man Werttypen nicht auf null vergleichen kann. Ansonsten klappt es so auch. Aber Enum.GetNames gefällt mir nach wie vor besser 🙂

23.03.2006 - 08:44 Uhr

Hallo der Marcel !

Also ich hoffe, Du hast meinen letzten Beitrag nicht als Vorwurf verstanden. Mir ging es mehr darum zu beschreiben, wie manchmal verschiedene Sichtweisen aufeinandertreffen können. Während es für eher praktisch orientierte Leute in der SW-Entwicklung (wie z.B. Dipl.Ings) halt oft darum geht, dass estwas "funktioniert" sind die eher theoretisch Veranlagteren oft an einer möglichst "sauberen" Lösung interessiert, die die klassischen OOD-Anforderungen möglichst umfassend erfüllt (Stichwort Pflegbarkeit, Erweiterbarkeit etc.).

Das Problem ist dass es oft schwer ist, jemandem der ja auch mal einige Jahre akademische Laufbahn hinter sich hat, aber der nie etwas von diesen Kriterien gehört hat - selbige zu vermitteln.

Was Du im Hinblick auf die Uni beschreibst kann ich aber auch als Informatiker nachvollziehen. Selbst im Informatik-Studium wird m.E. nach zu wenig spezialisiert. Es wird viel Wert gelegt auf Gedankenmodelle, die jetzt rein dem Software-Entwickler meist überhaupt nichts nutzen (Bsp. Turing-Maschinen o.Ä.). So kommt es auch garnicht selten vor, dass Diplom-Informatiker, die frisch von der Uni kommen, erstmal das Programmieren lernen müssen.

Ich denke das Hauptproblem in all diesen technischen Studiengängen ist, dass sie viel zu breit gefächert sind. Es wird immer versucht, Grundkenntnisse auf allen möglichen Teilbereichen zu vermitteln, so dass man am Ende "alles schonmal gehört hat" - aber meist von keinem Teil tiefergehende Fachkenntnisse besitzt.

Mehr Spezialisierungsmöglichkeiten wären hier meiner Meinung nach der richtige Schritt, denn in der Praxis kommt es später weniger darauf an, dass man bei allem mitreden kann, sondern dass man in seinem Arbeitsbereich stark ist. Ich habe z.B. an der Uni die Hardware-Entwicklungs Vorlesungen gehasst, weil mich dieser Bereich kaum interessiert, und bis heute hat noch niemand von mir verlangt, mal aus der SW-Abteilung kurz in die Produktion zu gehen und irgend einen Chip zusammen zu bauen.

22.03.2006 - 08:31 Uhr

Es ist wirklich so, dass viele SW-Entwickler heute aus artverwandten Bereichen z.B. E-Technik oder Maschinenbau kommen, und da fehlt dann vielleicht etwas der theoretische Hintergrund.

Ich hab mit Dipl.Ings. die Erfahrung gemacht, dass es meist als einziges Kriterium darauf ankommt, dass das Programm "funktioniert". Wenn man später, wenn ein Fehler aufgetreten ist, aber 2 Monate suchen muss um in dem Spaghetti-Code den Fehler aufspüren zu können, dann wird das oft mit Sprüchen wie "das ist immer so in der SW-Entwicklung" abgetan.

Also ich teile aus eigener Erfahrung die Bemerkungen hier zu einigen Dipl.Ings. Es gibt allerdings auch positive Exemplare 🙂