Hallo zusammen
Ich habe ein Problem mit einem Lock: irgendwie scheint das Mutual Exclusion bei C# nicht zu funktionieren? 8o
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
@JAck30lena
Kannst du mir ein wenig genauer erklären? Wovon sollen sie unterschiedliche Instanzen haben? Also ich instanziere diese Klasse nur einmal!
Done 👍
ja, der zweite Teil befindet sich der Methode HandleClient, welche BeginConnect als Delegatemethode übergeben wird
Habe ich gemacht: Ist dieselbe ID
Ich hatte schon daran gedacht, ob BeginConnect vielleicht das Delegate in demselben Thread aufruft, aber dann hatte ich dies hier entdeckt in der offiziellen Doku entdeckt:
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.
So geschafft... Dieser Code erzeugt denselben Fehler, allerdings tritt der Fehler nur im LAN mit einem sehr schnellen Netzwerk auf.
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;}
}
}
}
was meinst du damit?
edit: bitte beachte
Wichtig: [Hinweis] Wie poste ich richtig?
Punkt 10
durch deinen edit hast du meine bemerkung den kontext entrissen.
ähhmm... hallo? 🙂
sorry 😉
ich hab den code ein wenig aufpoliert mit debugausgaben. ich konnte jedoch das von dir beschriebene verhalten nciht reproduzieren?
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace etwasAnständiges
{
internal class Program
{
private readonly object obLoc;
private bool bErr;
private static void Main(string[] args)
{
new Program();
Console.In.Read();
}
public Program()
{
obLoc = new object();
Console.WriteLine("Attempt to enter Lock from:" + Thread.CurrentThread.GetHashCode());
lock (obLoc)
{
Console.WriteLine("Inside Lock from:" + Thread.CurrentThread.GetHashCode());
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s.Bind(new IPEndPoint(new IPAddress(new byte[] {127, 0, 0, 1}), 0));
s.Ttl = 10;
s.BeginConnect(new IPAddress(new byte[] {127, 0, 0, 1}), 80, HandleClient, null);
Thread.Sleep(5000); // do some work
if (bErr) Console.WriteLine("Schaaaaade, Windooooooof... Schaaaaade.....");
Console.WriteLine("Leaving Lock from:" + Thread.CurrentThread.GetHashCode());
}
Console.WriteLine("Free Lock from:" + Thread.CurrentThread.GetHashCode());
}
private void HandleClient(IAsyncResult Result)
{
Console.WriteLine("Attempt to enter Lock from:" + Thread.CurrentThread.GetHashCode());
lock (obLoc)
{
Console.WriteLine("Inside Lock from:" + Thread.CurrentThread.GetHashCode());
bErr = true;
Console.WriteLine("Leaving Lock from:" + Thread.CurrentThread.GetHashCode());
}
Console.WriteLine("Free Lock from:" + Thread.CurrentThread.GetHashCode());
}
}
}
Das ist mein Konsolenoutput
Attempt to enter Lock from:10
Inside Lock from:10
Attempt to enter Lock from:10
Inside Lock from:10
Leaving Lock from:10
Free Lock from:10
Schaaaaade, Windooooooof... Schaaaaade.....
Leaving Lock from:10
Free Lock from:10
Es fällt auf, dass es bei mir derselbe Thread ist 8o
OK, nun ist mir aufgefallen, dass es von Zeit zu Zeit geht. Manchmal sind es unterschiedliche Threads => dann funktionierts. Aber oft ist es derselbe Thread und dann funktionierts natürlich nicht. Die Frage ist nun, warum das Delegate oft in demselben Thread aufgerufen wird...
Von 10 Versuchen passiert 9mal ein Fehler und Zusammenhänge konnte ich bislang noch keine feststellen
Etwas ist mir jetzt doch aufgefallen:
Wenn ich die IP von www.google.de 74,125,43,103 anstatt diejenige von meinem Fileserver angebe, dann passiert der Fehler nicht..
Mir kommt es so vor als ob er keinen Separaten Thread für das Callback Delegate verwendet, falls er innerhalb einer sehr sehr kurzen Zeit eine Verbindung aufbauen kann...
Du musst in deinem Code auch EndConnect aufrufen, sonnst bekommst du ein Speicherleck.
Wird wohl so sein, dass unter bestimmten Umständen der Vorgang synchron ausgeführt wird. Um diesen Fall zu erkennen solltest du das IAsyncResult.CompletedSynchronously Property auswerten.
Hallo Zusammen
Laut Doku geht hier schon alles mit rechten Dingen zu. lock() verwendet ja intern einen Monitor. Und in der Monitor.Enter doku steht:
Derselbe Thread kann Enter mehrmals ausführen, ohne dass er blockiert wird.
Ich denke da musst du zusätzlich noch einen boolean nehmen um deinen Fall abzudecken.
Mfg Stefan