By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,864 Members | 1,285 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,864 IT Pros & Developers. It's quick & easy.

Locking and Async NetworkStream Operations

P: n/a
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
Feb 15 '06 #1
Share this Question
Share on Google+
4 Replies


P: n/a
> 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?


The situation you've described may happen when BeginWrite completes
synchronously ( it is not a bug ). This means that callback is executed from
within BeginWrite and in the same thread, that is why you reenter the lock
without blocking.

Why do you use locking here?
--
Regards, Vadym Stetsyak
www: http://vadmyst.blogspot.com
Feb 15 '06 #2

P: n/a
Hi Roman,

Thanks for posting!

As Vadym mentioned, if the current thread is not very busy, it will execute
the Asynchronous method by itself. Actually, this issue is not happened
frequently. So this is not a bug issue.

In addition, if you want to execute these methods synchronously, I don't
understand why you will choose the asynchronous callback method? Could you
please give me more explanation about the current issue? Thanks for your
understanding!

Regards,

Yuan Ren [MSFT]
Microsoft Online Support

Feb 16 '06 #3

P: n/a
> The situation you've described may happen when BeginWrite completes
synchronously.


That single sentence cleared up so many things thanks!
Well in that example locking might not make sence.

About why I need a Lock:
Let's say we have a List somewhere in the TestClass and some functions to
access it, add elements or remove elements. And because a thread could add an
element while the Callback is working with the list, I need to "lock" the
List for synchronizing List access.
I know, blocking on a Callback is evil but I don't see much other
possibilities.
Feb 16 '06 #4

P: n/a
Hi Roman,

Thanks for your reply!

For the current issue, I suggest you use the synchronizing thread for the
current issue. The following article shows where we can get the "Wait
Synchronization Technology Sample":
http://msdn.microsoft.com/library/de...us/cpsamples/h
tml/wait_synchronization_technology_sample.asp

I hope this will be helpful!

Regards,

Yuan Ren [MSFT]
Microsoft Online Support

Feb 21 '06 #5

This discussion thread is closed

Replies have been disabled for this discussion.