G
Guest
Hey all
While working with Async Methods and Networking I found something very
strange or better a bug?
To test it yourself create a new Windows Application with just a Button on
the Form.
Then modify the Code of the Form1 class until it looks like:
/****** BeginCode ******/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Net;
namespace WindowsApplication1 {
public partial class Form1 : Form {
TestClass c;
TcpClient cl;
public Form1() {
InitializeComponent();
Thread tr = new Thread(new ThreadStart(AcceptStuff));
tr.Start();
c = new TestClass();
}
public void AcceptStuff() {
TcpListener tcp = new TcpListener(IPAddress.Any, 1234);
tcp.Start();
cl = tcp.AcceptTcpClient();
}
private void button1_Click(object sender, EventArgs e) {
c.Add("bla");
}
}
class TestClass {
private object myLock = new object();
private MemoryStream m_memStream = new MemoryStream();
private NetworkStream m_netStream;
public TestClass() {
TcpClient tcp = new TcpClient("localhost", 1234);
m_netStream = tcp.GetStream();
}
public void Add(string bla) {
lock(myLock) {
Console.WriteLine("Lock1 locked");
byte[] buffer = Encoding.ASCII.GetBytes(bla);
m_netStream.BeginWrite(buffer, 0, buffer.Length, new
AsyncCallback(BeginWriteCallback), this);
Thread.Sleep(100);
Console.WriteLine("Lock1 unlocked");
}
}
private static void BeginWriteCallback(IAsyncResult ar) {
TestClass t = (TestClass)ar.AsyncState;
lock(t.myLock) {
Console.WriteLine("Lock2 locked");
t.m_netStream.EndWrite(ar);
Console.WriteLine("Lock2 unlocked");
}
}
}
}
/****** EndCode ******/
Now Point the Click-Event of your button to the Function:
button1_Click.
Now run the Application and Press the Button once.
You should see 4 Lines in your Debug View:
Lock1 locked
Lock1 unlocked
Lock2 locked
Lock2 unlocked
Looks good so far.
Now press the Button again and again and somewhen you'll see those 4 Lines:
Lock1 locked
Lock2 locked
Lock2 unlocked
Lock1 unlocked
Whao an already locked Object gets locked again?
Did I missunderstand something about the lock Statement? Or what's wrong
with it?
It's rather strange that this only occurs with the Async Method of a
NetworkStream, if I change it to a MemoryStream, it does never fail.
I guess this happens because the Async-Method is started from within the
Lock and when the Callback is fired, it somehow still thinks it's in that
locked Code-Part and doesn't try to lock again.
But it only happens sometimes and sometimes it does work (as you could test
yourself with the code above).
So anyone noticed something similiar? Is this a Bug in the Framework? Is
there any workaround?
Thanks for help
//Roman
While working with Async Methods and Networking I found something very
strange or better a bug?
To test it yourself create a new Windows Application with just a Button on
the Form.
Then modify the Code of the Form1 class until it looks like:
/****** BeginCode ******/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Net;
namespace WindowsApplication1 {
public partial class Form1 : Form {
TestClass c;
TcpClient cl;
public Form1() {
InitializeComponent();
Thread tr = new Thread(new ThreadStart(AcceptStuff));
tr.Start();
c = new TestClass();
}
public void AcceptStuff() {
TcpListener tcp = new TcpListener(IPAddress.Any, 1234);
tcp.Start();
cl = tcp.AcceptTcpClient();
}
private void button1_Click(object sender, EventArgs e) {
c.Add("bla");
}
}
class TestClass {
private object myLock = new object();
private MemoryStream m_memStream = new MemoryStream();
private NetworkStream m_netStream;
public TestClass() {
TcpClient tcp = new TcpClient("localhost", 1234);
m_netStream = tcp.GetStream();
}
public void Add(string bla) {
lock(myLock) {
Console.WriteLine("Lock1 locked");
byte[] buffer = Encoding.ASCII.GetBytes(bla);
m_netStream.BeginWrite(buffer, 0, buffer.Length, new
AsyncCallback(BeginWriteCallback), this);
Thread.Sleep(100);
Console.WriteLine("Lock1 unlocked");
}
}
private static void BeginWriteCallback(IAsyncResult ar) {
TestClass t = (TestClass)ar.AsyncState;
lock(t.myLock) {
Console.WriteLine("Lock2 locked");
t.m_netStream.EndWrite(ar);
Console.WriteLine("Lock2 unlocked");
}
}
}
}
/****** EndCode ******/
Now Point the Click-Event of your button to the Function:
button1_Click.
Now run the Application and Press the Button once.
You should see 4 Lines in your Debug View:
Lock1 locked
Lock1 unlocked
Lock2 locked
Lock2 unlocked
Looks good so far.
Now press the Button again and again and somewhen you'll see those 4 Lines:
Lock1 locked
Lock2 locked
Lock2 unlocked
Lock1 unlocked
Whao an already locked Object gets locked again?
Did I missunderstand something about the lock Statement? Or what's wrong
with it?
It's rather strange that this only occurs with the Async Method of a
NetworkStream, if I change it to a MemoryStream, it does never fail.
I guess this happens because the Async-Method is started from within the
Lock and when the Callback is fired, it somehow still thinks it's in that
locked Code-Part and doesn't try to lock again.
But it only happens sometimes and sometimes it does work (as you could test
yourself with the code above).
So anyone noticed something similiar? Is this a Bug in the Framework? Is
there any workaround?
Thanks for help
//Roman