Also ich würde sagen das Handle gibts nicht weil der Konstruktor nicht fertig ist. Bzw. durch die Asynchronität kann es vorkommen dass der Konstruktor noch nicht beendet ist.
Probier mal den Thread im Load Event zu starten, da müsste das Form ja schon existieren.
Aber der Code den du gepostet hast ist nur ein kleines Beispiel oder?
Ich meine für das was in der Funktion steht ist es ja nun wirklich nicht so sinnvoll nen neuen Thread anzulegen
Die Funktion ist auch nicht so mächtig. Es werden immer beide Ausdrücke ausgewertet, wenn man es ordentlich über C# Syntax macht wird nur der benötigte Ausdruck ausgewertet.
Sehr wichtig dann, wenn in der Kondition Division durch 0 oder null-Referenzen abgefangen werden sollen. Da bringt einem die Funktion genau garnichts.
Nebenbei kann einem da das IIf auch den Speicher zumüllen. Auch wenn man GC hat, muss man ja nicht alles liegen lassen wo es hinfällt.
Naja das was ihr aufzählt ist gerade für das konkrete Beispiel nicht allzu relevant.
Mir persönlich fallen 2 gute Gründe ein die Property dem public Feld zu bevorzugen:
1. Man kann später mal ein Interface mit dieser Property definieren, ohne viel Code zu ändern.
2. Man ist damit besser auf Änderungen vorbereitet. Rein C# syntaktisch macht es jetzt keinen Unterschied ob man das Feld jetzt zu ner Property ändert. Aber in der kompilierten Assembly macht es einen.
Ein Feld wird im IL Code anders zugegriffen als eine Property (die praktisch zu getter und setter Methoden umgewandelt wird).
Wenn jetzt also in einer Assembly Version auf ein Feld zugegriffen wird, wird das in Assemblies die darauf referenzieren auch so angewandt. Wenn man es dann in eine Property umwandeln würde müsste man alle Assemblies die diese Assembly benutzen neu erstellen und ausliefern.
Wenn es von Anfang an eine Property ist, muss man nur diese eine Assembly neu erstellen und ausliefern. Es ändert sich dann nur Code in der Assembly, aber nach Außen hat sich für die anderen nichts geändert.
Eigentlich scheiterst du an ganz einfachen Problemen.
Das Erste:
Die Reihenfolge. Geh mal mit nem Debugger schrittweise durch. Zu dem Zeitpunkt wo DoSomething ausgelöst wird, gibt es noch nicht mal das Objekt der zweiten Klasse.
Das Zweite:
Die Instanzen. Du erzeugst sowohl in ersteKlasse als auch in zweiteKlasse je eine Instanz von Test. Das sind zwei unterschiedliche Objekte die nichts voneinander wissen können. Warum sollte das eine also wissen, was bei dem anderen als Event eingetragen ist?
Naja ist eben der übliche Tausch: Speicher gegen Laufzeit.
256 Threads sind aber definitiv ein paar zu viel. Du kannst ja schauen ob du nen Mittelweg findest .
Also noch eine Methode erstellen der du den Bereich übergibst den sie scannen soll. Und diese arbeiten dann synchron mit je einem Ping. Davon laufen dann asynchron mehrere gleichzeitig.
Wo soll die Meldung angezeigt werden, wenn keiner eingeloggt ist?
Ich weiß nicht was der Dienst sonst noch so machen soll aber für das was du beschreibst wäre es sinnvoller ein normales Programm zu nehmen und ne Verknüpfung in Autostart zu erstellen.
Der Speicherverbrauch und der Absturz werden wohl daher kommen, dass du mit Threads nur so um dich schmeißt. 256 Threads sind dann doch etwas viel X_X
Außerdem ist das vieleicht nicht gerade die beste Idee nach einem asynchronen Aufruf das Objekt zu Disposen.
Meine Vorschläge wären:
- rufe scan asynchron auf und lass die Sends synchron laufen
- benutze nur ein Ping-Objekt. Kannst es doch (bei synchronen aufrufen) problemlos für alle deine Pings benutzen. Genauso musst du nicht für jeden Ping neue Daten erstellen.
Du könntest problemlos mit Reflection durch alle Klassen/Funktionen durchgehen, nach statischen Funktionen suchen die mit einem bestimmten Attribut versehen sind, und die dann ausführen.
Aber ich weiß nicht was an sowas gutes Design sein soll (auch bei der C++ Variante).
Man muss echt nicht jeden dreckigen Hack auspacken nur um ne Zeile Code zu sparen.
Ne simple Initialisierungsfunktion, da weißt du auch in 5 Jahren noch was dort passiert und in welcher Reihenfolge.
Damit brichst du das schließen ab und machst das Fenster nur unsichtbar. Und weil das nur bei UserClosing passiert, kriegt man noch problemlos das Programm beendet (z.B. Application.Exit )
Ich kapier einfach nicht, was der Vorteil von den Enums sein soll. Ich meine der Code um an den Faktor zu kommen sähe so aus:
double factor = (double)Einheiten.NeueEinheit;
Und wenn du ne neue Einheit hinzufügen würdest, müsstest du immernoch diesen Schritt gehen. Der Compiler überlegt sich ja nicht selbst was für ne Einheit du gern hättest.
Im Unterschied dazu mit Konstanten die in der Klasse Einheiten liegt:
double factor = Einheiten.NeueEinheit;
Wo soll der Enum dir denn da bitte Aufwand abnehmen?
1. Du musst im DataGridView DataMember auf den Namen der Tabelle im DataSet setzen damit was angezeigt wird.
2. Wenn du die Daten im DataSet per Code änderst, musst du DataGridView.Refresh() aufrufen, damit du die Änderungen siehst.
Die andere Richtung funktioniert automatisch. Sobald man die Zeile wechselt werden die Änderungen ins DataSet eingetragen. Aber auch das kannst du per Code erzwingen, sodass wenn man z.B. auf Speichern klickt auch wirklich alles gespeichert wird, egal ob man die Zeile vorher gewechselt hat oder nicht. Ist etwas umständlicher. Hier mal der Code dafür:
dataGridView1.EndEdit(); // beendet den Edit-Modus wenn man grad in einer Zelle was getippt hat
if( dataGridView1.IsCurrentRowDirty )
{
DataRowView rowView = (DataRowView)dataGridView1.CurrentRow.DataBoundItem;
rowView.EndEdit(); // schreibt die Werte der Zeile ins DataSet
}
Vieleicht kennt ja jemand noch was Besseres, wär auch für mich interessant
3. CheckBoxes werden automatisch erstellt, wenn du die Spalte als bool im DataSet anlegst:
dataSet1.Tables["tabelle1"].Columns.Add("spalte2",typeof(bool));
4. Du kannst bevor du das DataSet anschließt schon Spalten zum DataGridView hinzufügen. Die bleiben dann auch nach dem Setzen von DataSource erhalten. Der Trick ist: wenn du bei der Spalte die Eigenschaft DataPropertyName auf den Namen der Spalte in der Tabelle setzt, benutzt er selbstständig genau diese Spalte für die Werte aus dem DataSet.
Das heißt du kannst da nach belieben erstmal vorher selbstständig Spalten erstellen und die werden dann vom DataSet auch benutzt wenn du es entsprechend einstellst.
Wie ich heut nacht um 3 nicht schlafen konnte, hab ich auf 3sat den Ausführungen eines Dichters über die Regeln von Gedichten gelauscht. Ihr wisst schon: Reimschema, Zahl der Hebungen und andere abstraktere Regeln wie Einsibligkeit.
Eines hatte mir besonders Gefallen. Da ging es darum, dass Regeln auch gerne verletzt werden. Das Beispiel dafür war ein Gedicht dessen Regel 17 Worte war:
Zitat
Dreißigwortegedicht
Siebzehn Worte schreibe ich
auf dies leere Blatt,
acht hab’ ich bereits vertan,
jetzt schon sechzehn und
es hat alles längst mehr keinen Sinn,
ich schreibe lieber dreißig hin:
dreißig.
Das ist eben nur ein Wert der dir anzeigt, ob du gerade in DesignTime bist.
Z.B. wenn man ein Component schreibt, dass sich mit einem anderen PC verbinden soll. Es wär ja irgendwie blöd, wenn man die ganze Zeit während man mit dem Designer arbeitet ständig Fehler kriegt, dass die Verbindung nicht aufgebaut werden konnte.
Also steckt man den ganzen Aufbau kram hinter ein if( !DesignTime ) und es wird eben nicht zur Entwurfszeit ausgeführt.
Original von Traumzauberbaum
Der Manager soll doch aber auch synchronisiert sein.
Wenn du dir da den Decorator nicht dafür gedacht hast, muss man es anders machen. [...]
Wie gesagt, darum muss sich der Manager selbst auf "klassische" Weise kümmern.
Und genau dadurch kommt es zu Deadlocks. Weiß auch nicht wie ich dir das noch erklären soll. Der Code den du gepostet hast erzeugt keine Deadlocks. Aber wenn man es mit den anderen Synchronisationsanforderungen kombiniert steht man genauso schlau da wie vorher.
1. Es wird eine Funktion vom Manager aufgerufen. Der greift dazu auf ein Objekt zu.
2. Kurz vor dem zugriff wird auf dem Objekt ein Event ausgelöst. Dadurch bleibt der Manager am lock kleben.
3. Bei der Abarbeitung des Events muss das Objekt auf den Manager zugreifen und eine Funktion davon abrufen.
Folge:
A) Es laufen zwei Funktionen beim Manager nebeneinander, weil das nicht durch ein lock verhindert wurde
ODER
B) Das ausgelöste Event kann seine Funktion nicht fortsetzen, weil das nebeneinander ausführen von Funktionen vom Manager durch ein lock verhindert wird. Der Manager kann aber auch nicht fortsetzen, weil das Objekt noch das Event abarbeitet => Deadlock
Das glaub ich dir nicht, weil es schlicht unmöglich ist.
Kopier dir den Code mal ins Programm.
Es kann lediglich passieren, dass die Reihenfolge der Ausgabe unterschiedlich ist.
Das was du aber behauptest kann einfach garnicht passieren. Es ist unmöglich, weil die Variable string _name eine lokale Variable der Funktion WriteName ist.
Ich hab den Code mal geändert um das was du behauptest mal wirklich zu provozieren:
public class Programm
{
public static string _name = "name1";
public static object _lockObject = new object();
public static void Write(string name)
{
// lock eigentlich unnötig, wird auf nichts was außen liegt und sich ändert zugegriffen
Thread.Sleep(1000);
Console.WriteLine(name);
}
public static void WriteName( object name )
{
//string _name = name.ToString();
Console.WriteLine("Nutze " + _name);
Thread.Sleep( 1000 );
Write(_name);
}
static void Main(string[] args)
{
ParameterizedThreadStart start = WriteName;
Thread t = new Thread(start);
t.Start( _name );
Thread.Sleep(100);
_name = "name2";
WriteName( _name );
t.Join();
Console.ReadLine();
}
}
Das provoziert wirklich immer den Fehler. es wird erst "Nutze name1" geschrieben und dann gewartet. Währenddessen ändert sich die statische Variable _name. Erst dann geht es in der Funktion weiter.
Jetzt entferne die "//" bei "//string _name = name.ToString();" und es ist schlicht unmöglich, dass du das gleiche Verhalten beobachtest.
Der Manager soll doch aber auch synchronisiert sein.
Wenn du dir da den Decorator nicht dafür gedacht hast, muss man es anders machen. Aber gemacht werden muss es. Schließlich sollen auch solche Fälle synchronisiert werden:
- Event löst in Decorator A für Objekt A Methode A aus: Objekt A greift auf Methode A vom Decorator A für Manager A zu
- Manager A macht irgendwas
Das darf natürlich auch nicht gleichzeitig laufen, sondern soll synchronisiert sein.
Und dann kommt man wieder zu einem Deadlock wenn folgendes passiert:
- Event löst in Decorator A für Objekt A Methode A aus: Objekt A greift auf Methode A vom Decorator B für Manager A zu
- Manager A ruft für Decorator A für Objekt A Methode B auf
Manager A ist gerade beschäftigt, parallel darf er nichts anderes machen. Der Decorator A blockiert aber das, was der Manager machen will. Parallel dazu versucht der Decorator B auf dem Manager was ausführen zu lassen. Der lässt das aber nicht zu, weil eben immer nur eine Funktion gleichzeitig laufen darf.
Nein ich meinte wenn die Funktionen nicht auf den Manager zugreifen.
Folgendes Beispiel soll ja auch synchronisiert werden:
Event löst in Objekt A Methode A aus
Manager greift auf Objekt A Methode B zu
Genau da kannst du es nicht vermeiden, dass sich die Objekte auch selbst um synchronisation kümmern, das ist Teil der Anforderung.
Wenn du sowas einfach zulassen kannst, gibts keinen Grund das Objekt überhaupt irgendwie zu synchronisieren. Dann macht man locks nur beim Manager und lässt den Rest halt laufen, und hat das Problem auch nicht.
So oder so, deine Lösung ist unwirksam. Entweder man braucht sie nicht, weil die Objekte nicht synchronisiert werden müssen. Oder sie führt genauso zu Deadlocks.