Lock funktioniert nicht
-
Hallo zusammen
Ich habe ein Problem mit einem Lock: irgendwie scheint das Mutual Exclusion bei C# nicht zu funktionieren?Erste Codeschnipsel:
// make sure no other thread is currently manipulating the sockets lock(this.obLoc){ // create a server socket and listen for incoming connection attempts this.skSrv = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); //this.skSrv.Bind(new IPEndPoint(this.ipLoc,this.nmPrt)); //this.skSrv.Listen(1); //this.skSrv.BeginAccept(this.HandleServer,null); // try to establish a client - connection simultaneously this.skDta = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); this.skDta.Bind(new IPEndPoint(this.ipLoc,0)); this.skDta.Ttl = 10; this.skDta.BeginConnect(this.ipRmt,this.nmPrt,this.HandleClient,null); // WTF: Zwischen diesen beiden Zeilen wird der komplette Code aus dem zweiten Teil ausgeführt... // adjust the status this.stSta = "Connecting to "+this.ipRmt+":"+this.nmPrt; }
Zweites Codeschnipsel:
// make sure no other thread is currently manipulating the sockets lock(this.obLoc){ // check if no server connection has been established in the meantime if(this.skSrv != null){ // open a try - statement as an exception may occure try{ // try to end the current client connection process this.skDta.EndConnect(Result); // close and set null the server - socket immediatly this.skSrv.Close(); this.skSrv = null; // adjust the status this.stSta = "Connected with "+this.ipRmt+":"+this.nmPrt+" as Client"; } // a socket - exception has occurred catch(Exception exp) { // make another connection - attempt this.skDta.BeginConnect(this.ipRmt,this.nmPrt,this.HandleClient,null); } } }
Leider springt der Code munter von einem Lock ins andere und zurück, wie ist das Möglich?
Mfg Samuel
-
Wie ist denn this.obLoc deklariert ?
Btw.: Einrücken und die richtigen Codetags verwenden bringt mehr in Sachen lesbarkeit
-
// ----------------------------------- default constructor ---------------------------------- public Tcp(){ // create a new buffer for buffering incoming traffic and set the status to disconnected this.lsBuf = new List<byte>(16); this.stSta = "Disconnected"; this.obLoc = new object(); } // ------------------------------------------------------------------------------------------
Sorry wegen dem Einrücken :p
-
// WTF: Zwischen diesen beiden Zeilen wird der komplette Code aus dem zweiten Teil ausgeführt...
Wie jetzt? Steht das zweite Lock im Ersten?
-
Du hast nicht zufällig mehr als ein Tcp-Objekt?
-
@MFK
Nein habe ich nicht und ich habe auch die Instanz des internen lockobjects im Debugger mit MakeObjectID überprüft. Es ist dasselbe Objekt@Jockelx
Der zweite Block ist ein Teil der Methode HandleClient, welche als Delegate an BeginConnect des ersten blockes übergeben wird.Das hier habe ich aus der offiziellen Doku entnommen:
When your application calls BeginConnect, the system will use a separate thread to execute the specified callback method, and will block on EndConnect until the Socket connects successfully or throws an exception.
-
using System; using System.Net; using System.Net.Sockets; namespace Fuck{ class Program{ private object obLoc; private bool bErr; static void Main(string[] args){ new Program(); Console.In.Read(); } public Program(){ this.obLoc = new object(); lock(this.obLoc) { Socket s = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); s.Bind(new IPEndPoint(new IPAddress(new byte[] { 192,168,2,6 }),0)); s.Ttl = 10; s.BeginConnect(new IPAddress(new byte[] { 192,168,2,8 }),80,this.HandleClient,null); if(this.bErr) Console.WriteLine("Schaaaaade, Windooooooof... Schaaaaade....."); } } private void HandleClient(IAsyncResult Result){ lock(this.obLoc) {this.bErr = true;} } } }
Dieser Code erzeugt denselben Fehler, allerdings tritt der Fehler nur im LAN mit einem sehr schnellen Netzwerk auf.
-
Oh Mann, nix verstehen aber immer gleich rummaulen. Schaaaaaaade Ishildur
-
lock() lockt "rekursiv", d.h. du kannst im selben Thread das selbe Objekt mehrfach locken
-
die BeginXxx Funktionen dürfen den CompletionHandler auch "direkt" aufrufen, also synchron, nämlich dann, wenn der IO sofort abgeschlossen wurde
Was folgt daraus? Man muss beim Verwenden der BeginXxx Funktionen einfach aufpassen, dass es dem Programm nix ausmacht, wenn eben das passiert.
Grmpf!
-
-
@hustbear
Windoooof war eigentlich mehr im Scherz gedacht (nicht immer alles so ernst nehmen) :p
Aber dass ich noch nicht viel davon verstehe, stimmt! Ich kenne mich zwar relativ gut mit Multithreading aus, allerdings nicht auf der .NET Plattform.
-
Ich kenne mich zwar relativ gut mit Multithreading aus, allerdings nicht auf der .NET Plattform.
Spielt denn die Plattform wirklich eine soooo grosse Rolle?
Simon
-
@theta: naja mann muss schon die Spielregeln der Libraries kennen die man verwendet. Andere Libraries garantieren z.B. dass der Completion-Handler immer asynchron ausgeführt wird, auch wenn die Operation synchron abgeschlossen werden konnte. Das .NET Framework macht es aber anders. Wenn man das nicht weiss, bzw. nicht damit rechnet, fliegt man auf die Schnauze.
-
@hustbaer
Genau das ist mir passiertIch bin davon ausgegangen, dass der Code des delegates niemals ausgeführt werden kann, solange die Initialisierung der Client-/ und Serversockets nicht komplett abgeschlossen ist. Doch genau das passierte eben, wenn die Operation synchron ausgeführt wurde, weil dadurch das lock ausgehebelt wurde
Ich bedanke mich vielmals für die nützlichen Hinweise
-
"immer asynchron" ist IMO auch der bessere Weg, weil einfacher und daher weniger Fehleranfällig. IMO eine Fehlentscheidung, aber das .NET Framework ist ja geradezu voll davon.