Skip to search.

Breaking News Visit Yahoo! News for the latest.

×Close this window

PowerThreading · Richter/Wintellect Power Threading

The Yahoo! Groups Product Blog

Check it out!

Group Information

  • Members: 320
  • Category: Software
  • Founded: Jun 26, 2008
  • Language: English
? Already a member? Sign in to Yahoo!

Yahoo! Groups Tips

Did you know...
Message search is now enhanced, find messages faster. Take it for a spin.

Messages

Advanced
Messages Help
Messages 561 - 591 of 1095   Oldest  |  < Older  |  Newer >  |  Newest
Messages: Show Message Summaries Sort by Date ^  
#561 From: "Jeffrey Richter (Wintellect LLC)" <JeffreyR@...>
Date: Tue Aug 4, 2009 6:07 pm
Subject: RE: Semantic of WaintHandle from AsyncEnumerator.BeginExecute's AsyncResult
jeffrey.richter
Send Email Send Email
 

I cannot repro the problem you describe.

I just wrote this:

      var ae = new AsyncEnumerator();

      IAsyncResult ar = ae.BeginExecute(Foo(ae), null, null);

      ar.AsyncWaitHandle.WaitOne();

      ae.EndExecute(ar);

 

    private static IEnumerator<Int32> Foo(AsyncEnumerator ae) {

        yield return 1;

    }

 

And WaitOne blocks forever proving that the event is NOT signaled. I can’t explain the results your’re seeing.

The code you show looks right to me however I would suggest NOT disposing of the handle; my code will do then when EndExecute is called.

-- Jeffrey Richter (http://Wintellect.com)

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of evilshrike
Sent: Tuesday, August 04, 2009 10:23 AM
To: PowerThreading@yahoogroups.com
Subject: [PowerThreading] Semantic of WaintHandle from AsyncEnumerator.BeginExecute's AsyncResult

 

 

Hello.

I have some my component which uses AsynEnumerator internally and this component contains some method:
public void DoWork()
{
m_asyncEnumerator = new AsyncEnumerator();
m_asyncEnumerator.BeginExecute(
doRealWork(), m_asyncEnumerator.EndExecute);
}
it's very straightforward.
Now I want the method DoWork returns a WaitHandle which could be used by client to wait for a result.
(sure I could create BeginDoWork and EndDoWork, but I prefer WaitHandle)
It's correct, isn't?

So I'm changing the method to:
public WaintHandle DoWork()
{
m_asyncEnumerator = new AsyncEnumerator();
return m_asyncEnumerator.BeginExecute(
doRealWork(),
m_asyncEnumerator.EndExecute).AsyncWaitHandle;
}
Is it still correct?

Then I try to use the new method:

using (WaitHandle wh = component.DoWork())
{
wh.WaitOne();
}
Assert.IsTrue(component.IsCompleted) // check state

The thing is that after WaitHandle signals it's complete component's doRealWork is not complete. It seems that WaitHandle (received from AsyncEnumerator.BeginExecute's AsyncState ) signals right after first "yield return 1".
Is it by design? What is semantic of WaitHandle in AsyncResult from AsyncEnumerator.BeginExecute call?


#562 From: "evilshrike" <evilshrike@...>
Date: Thu Aug 6, 2009 3:41 pm
Subject: When to use AsyncEnumerator.End's parameters
evilshrike
Send Email Send Email
 
What's difference between this code:
using (Stream fs = new FileStream(sTempFile ))
{
	 fs.BeginWrite(buffer, 0, nRead, ae.End(), null);
	 yield return 1;
	 fs.EndWrite(ae.DequeueAsyncResult());
}

and this one (notice AsyncEnumerator.End's param):
using (Stream fs = new FileStream(sTempFile ))
{
	 fs.BeginWrite(buffer, 0, nRead, ae.End(fs.EndWrite), null);
	 yield return 1;
	 fs.EndWrite(ae.DequeueAsyncResult());
}

Is there any sence in passing fs.EndWrite to ae.End method? When should I do
this?

What will change if I add cancelation:

using (Stream fs = new FileStream(sTempFile ))
{
	 fs.BeginWrite(buffer, 0, nRead, ae.End(), null);
	 yield return 1;
	 if (ae.IsCanceled())
	 {
		 ae.DiscardGroup(0);
		 yield break;
	 }
	 fs.EndWrite(ae.DequeueAsyncResult());
}
Is it correct? Or I should pass fs.EndWrite to ae.End() ?

Thnx in advance.

#563 From: "evilshrike" <evilshrike@...>
Date: Thu Aug 6, 2009 3:43 pm
Subject: Re: Semantic of WaintHandle from AsyncEnumerator.BeginExecute's AsyncResult
evilshrike
Send Email Send Email
 
Sorry for this. I tried to delete the post. And it seemed to be deleted but not.

#564 From: "Jeffrey Richter (Wintellect LLC)" <JeffreyR@...>
Date: Thu Aug 6, 2009 4:42 pm
Subject: RE: When to use AsyncEnumerator.End's parameters
jeffrey.richter
Send Email Send Email
 

My AsyncEnumerator class has 2 overloaded End methods:

      public AsyncCallback End();

     public AsyncCallback End(int group, AsyncEnumerator.EndObjectXxx callback);

 

The most commonly used of these is the first, End().

The End method that takes an int group is used when you want to take advantage of AE’s discard feature; described in this magazine column: http://msdn.microsoft.com/en-us/magazine/cc721613.aspx#id0390064.

If you do not have the AE discard the in-coming IAsyncResult automatically, then the group and the EndObjectXxx delegate are not used.

If you have the AE automatically discard the in-coming IAsyncResult, then you can have it discard all incoming IAsyncResults that are part of a specific group by calling:

void DiscardGroup(int group);

If the AE does discard an IAsyncReuslt for you, it does so by calling an EndXxx method which you passed as the EndObjectXxx delegate to AE’s End method.

 

My AsyncEnumerator class also has this method:

      public AsyncCallback EndVoid(int group, AsyncEnumerator.EndVoidXxx callback);

 

This method works just like the End method that takes an EndObjectXxx but it allows you to pass an EndXxx method that returns ‘void’.

 

Your 2nd sample below won’t actually compile because there is no End method that takes just a delegate without also taking a discard group.

However, if you passed a discard group Int32, then the 2 samples would behave identically.

 

In your 3rd sample, you will get an exception thrown if the AE is canceled because the operation will complete, its IAsyncResult will come in, the AE will try to discard the IAsyncResult but it can’t because you didn’t specify a discard group and an EndObjectXxx delegate when calling AE’s End method.

 

Also, it is not necessary to call DiscardGroup if you exit the iterator entirely. Because, when you exit the iterator entirely (yield break), then I automatically discard all groups for you – this can simplify your code some.

One more thing…If you intend to use cancelation, then you can call this method at the top of your iterator:

void ThrowOnMissingDiscardGroup(true);

 

This method tells the AE object that you intend to use cancelation, can if you ever call the End method that doesn’t take a discard group and a callback, an exception will immediately be thrown as opposed to an exception occurring only if cancelation actually does occur.

-- Jeffrey Richter (http://Wintellect.com)

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of evilshrike
Sent: Thursday, August 06, 2009 8:41 AM
To: PowerThreading@yahoogroups.com
Subject: [PowerThreading] When to use AsyncEnumerator.End's parameters

 

 

What's difference between this code:
using (Stream fs = new FileStream(sTempFile ))
{
fs.BeginWrite(buffer, 0, nRead, ae.End(), null);
yield return 1;
fs.EndWrite(ae.DequeueAsyncResult());
}

and this one (notice AsyncEnumerator.End's param):
using (Stream fs = new FileStream(sTempFile ))
{
fs.BeginWrite(buffer, 0, nRead, ae.End(fs.EndWrite), null);
yield return 1;
fs.EndWrite(ae.DequeueAsyncResult());
}

Is there any sence in passing fs.EndWrite to ae.End method? When should I do this?

What will change if I add cancelation:

using (Stream fs = new FileStream(sTempFile ))
{
fs.BeginWrite(buffer, 0, nRead, ae.End(), null);
yield return 1;
if (ae.IsCanceled())
{
ae.DiscardGroup(0);
yield break;
}
fs.EndWrite(ae.DequeueAsyncResult());
}
Is it correct? Or I should pass fs.EndWrite to ae.End() ?

Thnx in advance.


#565 From: "evilshrike" <evilshrike@...>
Date: Thu Aug 6, 2009 5:26 pm
Subject: Re: When to use AsyncEnumerator.End's parameters
evilshrike
Send Email Send Email
 
Thank you for detailed answer!
In other words it's better always specify a EndXXX-callback for AE.End() and
call ThrowOnMissingDiscardGroup(true)?
Because if there will be cancelation it's the only way to go if not is't safer
code for future changes, right?


--- In PowerThreading@yahoogroups.com, "Jeffrey Richter (Wintellect LLC)"
<JeffreyR@...> wrote:
>
> My AsyncEnumerator class has 2 overloaded End methods:
>       public AsyncCallback End();
>      public AsyncCallback End(int group, AsyncEnumerator.EndObjectXxx
callback);
>
> The most commonly used of these is the first, End().
> The End method that takes an int group is used when you want to take advantage
of AE's discard feature; described in this magazine column:
http://msdn.microsoft.com/en-us/magazine/cc721613.aspx#id0390064.
> If you do not have the AE discard the in-coming IAsyncResult automatically,
then the group and the EndObjectXxx delegate are not used.
> If you have the AE automatically discard the in-coming IAsyncResult, then you
can have it discard all incoming IAsyncResults that are part of a specific group
by calling:
> void DiscardGroup(int group);
> If the AE does discard an IAsyncReuslt for you, it does so by calling an
EndXxx method which you passed as the EndObjectXxx delegate to AE's End method.
>
> My AsyncEnumerator class also has this method:
>       public AsyncCallback EndVoid(int group, AsyncEnumerator.EndVoidXxx
callback);
>
> This method works just like the End method that takes an EndObjectXxx but it
allows you to pass an EndXxx method that returns 'void'.
>
> Your 2nd sample below won't actually compile because there is no End method
that takes just a delegate without also taking a discard group.
> However, if you passed a discard group Int32, then the 2 samples would behave
identically.
>
> In your 3rd sample, you will get an exception thrown if the AE is canceled
because the operation will complete, its IAsyncResult will come in, the AE will
try to discard the IAsyncResult but it can't because you didn't specify a
discard group and an EndObjectXxx delegate when calling AE's End method.
>
> Also, it is not necessary to call DiscardGroup if you exit the iterator
entirely. Because, when you exit the iterator entirely (yield break), then I
automatically discard all groups for you - this can simplify your code some.
> One more thing...If you intend to use cancelation, then you can call this
method at the top of your iterator:
> void ThrowOnMissingDiscardGroup(true);
>
> This method tells the AE object that you intend to use cancelation, can if you
ever call the End method that doesn't take a discard group and a callback, an
exception will immediately be thrown as opposed to an exception occurring only
if cancelation actually does occur.
> -- Jeffrey Richter (http://Wintellect.com<http://wintellect.com/>)
>
> From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com]
On Behalf Of evilshrike
> Sent: Thursday, August 06, 2009 8:41 AM
> To: PowerThreading@yahoogroups.com
> Subject: [PowerThreading] When to use AsyncEnumerator.End's parameters
>
>
>
> What's difference between this code:
> using (Stream fs = new FileStream(sTempFile ))
> {
> fs.BeginWrite(buffer, 0, nRead, ae.End(), null);
> yield return 1;
> fs.EndWrite(ae.DequeueAsyncResult());
> }
>
> and this one (notice AsyncEnumerator.End's param):
> using (Stream fs = new FileStream(sTempFile ))
> {
> fs.BeginWrite(buffer, 0, nRead, ae.End(fs.EndWrite), null);
> yield return 1;
> fs.EndWrite(ae.DequeueAsyncResult());
> }
>
> Is there any sence in passing fs.EndWrite to ae.End method? When should I do
this?
>
> What will change if I add cancelation:
>
> using (Stream fs = new FileStream(sTempFile ))
> {
> fs.BeginWrite(buffer, 0, nRead, ae.End(), null);
> yield return 1;
> if (ae.IsCanceled())
> {
> ae.DiscardGroup(0);
> yield break;
> }
> fs.EndWrite(ae.DequeueAsyncResult());
> }
> Is it correct? Or I should pass fs.EndWrite to ae.End() ?
>
> Thnx in advance.
>

#567 From: "Jeffrey Richter (Wintellect LLC)" <JeffreyR@...>
Date: Thu Aug 6, 2009 8:50 pm
Subject: RE: AsyncEnumerator.BeginExecute question
jeffrey.richter
Send Email Send Email
 
Send me some code.

--Jeffrey Richter (http://Wintellect .com)


From: bonneteit <ebonnett@...>
Sent: Thursday, August 06, 2009 12:36 PM
To: PowerThreading@yahoogroups.com <PowerThreading@yahoogroups.com>
Subject: [PowerThreading] AsyncEnumerator.BeginExecute question

 

I am calling my static class called PowerThreadingSocketClient from a Console app. I call the Start method, just like it shows in the example. From there, I new up an AsyncEnumerator and call BeginExecute passing my Process method in (and a couple of other params). In the Process method, I am transferring a/some large file(s). However, the BeginExecute, being async, returns right away and the Start method ends. This is closing my client socket immediately. I put a Console.Read in there and the file xfers but that isn't going to work in a real situation.

Is there something I'm missing? Do I have to pass in a Socket instead of creating it in the Process method?

TIA,

Evan


#568 From: "Jeffrey Richter (Wintellect LLC)" <JeffreyR@...>
Date: Thu Aug 6, 2009 8:53 pm
Subject: RE: Re: When to use AsyncEnumerator.End's parameters
jeffrey.richter
Send Email Send Email
 
Yes, it is safer to always pass discard group/end method but it is very inconvenient in scenarios where you don't need discard/cancel.

--Jeffrey Richter (http://Wintellect .com)


From: evilshrike <evilshrike@...>
Sent: Thursday, August 06, 2009 10:28 AM
To: PowerThreading@yahoogroups.com <PowerThreading@yahoogroups.com>
Subject: [PowerThreading] Re: When to use AsyncEnumerator.End's parameters

 

Thank you for detailed answer!
In other words it's better always specify a EndXXX-callback for AE.End() and call ThrowOnMissingDiscardGroup(true)?
Because if there will be cancelation it's the only way to go if not is't safer code for future changes, right?

--- In PowerThreading@yahoogroups.com, "Jeffrey Richter (Wintellect LLC)" <JeffreyR@...> wrote:
>
> My AsyncEnumerator class has 2 overloaded End methods:
> public AsyncCallback End();
> public AsyncCallback End(int group, AsyncEnumerator.EndObjectXxx callback);
>
> The most commonly used of these is the first, End().
> The End method that takes an int group is used when you want to take advantage of AE's discard feature; described in this magazine column: http://msdn.microsoft.com/en-us/magazine/cc721613.aspx#id0390064.
> If you do not have the AE discard the in-coming IAsyncResult automatically, then the group and the EndObjectXxx delegate are not used.
> If you have the AE automatically discard the in-coming IAsyncResult, then you can have it discard all incoming IAsyncResults that are part of a specific group by calling:
> void DiscardGroup(int group);
> If the AE does discard an IAsyncReuslt for you, it does so by calling an EndXxx method which you passed as the EndObjectXxx delegate to AE's End method.
>
> My AsyncEnumerator class also has this method:
> public AsyncCallback EndVoid(int group, AsyncEnumerator.EndVoidXxx callback);
>
> This method works just like the End method that takes an EndObjectXxx but it allows you to pass an EndXxx method that returns 'void'.
>
> Your 2nd sample below won't actually compile because there is no End method that takes just a delegate without also taking a discard group.
> However, if you passed a discard group Int32, then the 2 samples would behave identically.
>
> In your 3rd sample, you will get an exception thrown if the AE is canceled because the operation will complete, its IAsyncResult will come in, the AE will try to discard the IAsyncResult but it can't because you didn't specify a discard group and an EndObjectXxx delegate when calling AE's End method.
>
> Also, it is not necessary to call DiscardGroup if you exit the iterator entirely. Because, when you exit the iterator entirely (yield break), then I automatically discard all groups for you - this can simplify your code some.
> One more thing...If you intend to use cancelation, then you can call this method at the top of your iterator:
> void ThrowOnMissingDiscardGroup(true);
>
> This method tells the AE object that you intend to use cancelation, can if you ever call the End method that doesn't take a discard group and a callback, an exception will immediately be thrown as opposed to an exception occurring only if cancelation actually does occur.
> -- Jeffrey Richter (http://Wintellect.com<http://wintellect.com/>)
>
> From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of evilshrike
> Sent: Thursday, August 06, 2009 8:41 AM
> To: PowerThreading@yahoogroups.com
> Subject: [PowerThreading] When to use AsyncEnumerator.End's parameters
>
>
>
> What's difference between this code:
> using (Stream fs = new FileStream(sTempFile ))
> {
> fs.BeginWrite(buffer, 0, nRead, ae.End(), null);
> yield return 1;
> fs.EndWrite(ae.DequeueAsyncResult());
> }
>
> and this one (notice AsyncEnumerator.End's param):
> using (Stream fs = new FileStream(sTempFile ))
> {
> fs.BeginWrite(buffer, 0, nRead, ae.End(fs.EndWrite), null);
> yield return 1;
> fs.EndWrite(ae.DequeueAsyncResult());
> }
>
> Is there any sence in passing fs.EndWrite to ae.End method? When should I do this?
>
> What will change if I add cancelation:
>
> using (Stream fs = new FileStream(sTempFile ))
> {
> fs.BeginWrite(buffer, 0, nRead, ae.End(), null);
> yield return 1;
> if (ae.IsCanceled())
> {
> ae.DiscardGroup(0);
> yield break;
> }
> fs.EndWrite(ae.DequeueAsyncResult());
> }
> Is it correct? Or I should pass fs.EndWrite to ae.End() ?
>
> Thnx in advance.
>


#569 From: Nikos Baxevanis <baxevanis@...>
Date: Fri Aug 7, 2009 1:52 pm
Subject: RE: AsyncEnumerator.BeginExecute question
n.baxevanis
Send Email Send Email
 
Hi Evan,
 
All you need to do is have your Process method call again the static method that creates the AE.
Since all this is happening on a threadpool thread you may stop the program anytime by hitting any key.
There is a very good example in \PowerThreading\PowerThreading-Samples\AsyncEnumerator\TcpServer
You may also look at the following code,
 
    internal sealed class Program {
        private static void Main() {
            TcpListener listener = new TcpListener(addr, tcpPort);
            listener.Start();
            ConnectionListener.Start(listener);
            Console.ReadLine(); // Wait for the user to press any key and exit.
            listener.Stop();
        }
    }
 
    internal static class ConnectionListener {
        public static void Start(TcpListener listener) {
            AsyncEnumerator ae = new AsyncEnumerator();
            ae.BeginExecute(Process(ae,
                listener), ae.EndExecute, null);
        }
        private static IEnumerator<Int32> Process(AsyncEnumerator ae, TcpListener listener) {
            listener.BeginAcceptSocket(ae.End(), null);
            yield return 1;
            Socket socket;
            try {  socket = listener.EndAcceptSocket(ae.DequeueAsyncResult()); }
            catch (ObjectDisposedException) { yield break;}
            Start(listener); // Accept another client.
            // You may call sockets BeginXxx, EndXxx methods here using AE.
            // ...
        }
    }

           

-Nikos Baxevanis           
 

To: PowerThreading@yahoogroups.com
From: ebonnett@...
Date: Thu, 6 Aug 2009 19:35:39 +0000
Subject: [PowerThreading] AsyncEnumerator.BeginExecute question

 
I am calling my static class called PowerThreadingSocketClient from a Console app. I call the Start method, just like it shows in the example. From there, I new up an AsyncEnumerator and call BeginExecute passing my Process method in (and a couple of other params). In the Process method, I am transferring a/some large file(s). However, the BeginExecute, being async, returns right away and the Start method ends. This is closing my client socket immediately. I put a Console.Read in there and the file xfers but that isn't going to work in a real situation.

Is there something I'm missing? Do I have to pass in a Socket instead of creating it in the Process method?

TIA,

Evan




Μείνετε συνδεδεμένοι με τους φίλους σας στο Zoo Κάντε κλικ εδώ!

#570 From: "bonneteit" <ebonnett@...>
Date: Fri Aug 7, 2009 5:30 pm
Subject: Re: AsyncEnumerator.BeginExecute question
bonneteit
Send Email Send Email
 

Here is the code.  This is a test harness for the class.  I added a hashtable that includes the ip:port.  I query the hashtable to see if it contains that entry and have a bool as the value (isBusy).  If it's busy, I sleep for 10 sec.  I'll be interested in any feedback.  BTW... love the AE.  Brilliance! Sheer, unadulterated brilliance!

 

class Program

{

static void Main(string[] args)

{

string[] files = Properties.Settings.Default.FilePath.Split(';');

string server = "xxx.xxx.xxx.xxx";

int port = 52000;

foreach (string file in files)

{

Console.WriteLine("Sending " + file + " to Server...");

PowerThreadingClient.Start(server, port, file);

while (PowerThreadingClient.IsBusy(server, port))

{

Thread.Sleep(10000);

}

}

}

}


 

public static class PowerThreadingClient

{

private static Hashtable _processingTable = new Hashtable();

#region Start

public static void Start(String hostNameOrAddress, Int32 port, String filePath)

{

AsyncEnumerator ae = new AsyncEnumerator();

ae.BeginExecute(ProcessWithPacketHashing(ae, hostNameOrAddress, port, filePath), ae.EndExecute, null);

}

#endregion

#region ProcessWithPacketHashing

private static IEnumerator<Int32> ProcessWithPacketHashing(AsyncEnumerator ae, String hostNameOrAddress, Int32 port, String filePath)

{

if (!File.Exists(filePath))

throw new FileNotFoundException(string.Format("{0} could not be found.", filePath));

IPAddress[] ipAddresses;

EndPoint endPoint;

Socket client = null;

if (!_processingTable.ContainsKey(string.Format("{0}:{1}", hostNameOrAddress, port)))

_processingTable.Add(string.Format("{0}:{1}", hostNameOrAddress, port), true);

ipAddresses = Dns.GetHostAddresses(hostNameOrAddress);

endPoint = new IPEndPoint(ipAddresses[0], port);

using (client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP))

{

string fileDir = Path.GetDirectoryName(filePath);

string hash = HashFile(filePath);

byte[] fileInfo = GetFileInfoBytes(filePath, hash);

byte[] filePositionBytes = new byte[8];

client.BeginConnect(endPoint, ae.End(), null);

yield return 1;

client.EndConnect(ae.DequeueAsyncResult());

client.BeginSend(fileInfo, 0, fileInfo.Length, SocketFlags.None, ae.End(), null);

yield return 1;

int bytesSent = client.EndSend(ae.DequeueAsyncResult());

client.BeginReceive(filePositionBytes, 0, filePositionBytes.Length, SocketFlags.None, ae.End(), null);

yield return 1;

int bytesReceived = client.EndReceive(ae.DequeueAsyncResult());

Int64 filePosition = 0;

if (bytesReceived == 8)

{

filePosition = BitConverter.ToInt64(filePositionBytes, 0);

Console.WriteLine("Got the file start position: " + filePosition);

}

Int64 bytesToSend = 0;

using (FileStream fs = File.OpenRead(filePath))

{

Byte[] fileBytes;

bytesToSend = fs.Length - filePosition;

// Set the fileBytes, the bytes we will read from the file, equal to the max buffer size less the size of the packet hash size and 4 bytes for an int that tells the server how much data to expect

fileBytes = new Byte[Properties.Settings.Default.MaxBufferSize - Properties.Settings.Default.SHA256Length - 4];

if (fs.CanSeek)

fs.Seek(filePosition, SeekOrigin.Begin);

while (bytesToSend != 0)

{

if (bytesToSend < fileBytes.Length)

Array.Resize(ref fileBytes, (int)bytesToSend);

for (int bytesReadSoFar = 0; bytesReadSoFar < fileBytes.Length; )

{

int bytesReadThisTime = fs.Read(fileBytes, bytesReadSoFar, fileBytes.Length - bytesReadSoFar);

bytesReadSoFar += bytesReadThisTime;

}

string packetHash = SHA256Utils.GenerateSHA256Hash(fileBytes);

Byte[] packetHashBytes = Convert.FromBase64String(packetHash);

Byte[] hashAndData = new Byte[fileBytes.Length + packetHashBytes.Length + 4];

Byte[] dataLengthBytes = BitConverter.GetBytes(hashAndData.Length);

Array.Copy(dataLengthBytes, hashAndData, dataLengthBytes.Length);

Array.Copy(packetHashBytes, 0, hashAndData, dataLengthBytes.Length, packetHashBytes.Length);

Array.Copy(fileBytes, 0, hashAndData, dataLengthBytes.Length + packetHashBytes.Length, fileBytes.Length);

client.BeginSend(hashAndData, 0, hashAndData.Length, SocketFlags.None, ae.End(), null);

yield return 1;

client.EndSend(ae.DequeueAsyncResult());

bytesToSend -= fileBytes.Length;

}

}

client.BeginDisconnect(true, ae.End(), null);

yield return 1;

client.EndDisconnect(ae.DequeueAsyncResult());

Console.WriteLine("Socket Disconnected");

_processingTable.Remove(string.Format("{0}:{1}", hostNameOrAddress, port));

}

}

#endregion

#region Process

private static IEnumerator<Int32> Process(AsyncEnumerator ae, String hostNameOrAddress, Int32 port, String filePath)

{

if (!File.Exists(filePath))

throw new FileNotFoundException(string.Format("{0} could not be found.", filePath));

IPAddress[] ipAddresses;

EndPoint endPoint;

Socket client = null;

if (!_processingTable.ContainsKey(string.Format("{0}:{1}", hostNameOrAddress, port)))

_processingTable.Add(string.Format("{0}:{1}", hostNameOrAddress, port), true);

ipAddresses = Dns.GetHostAddresses(hostNameOrAddress);

endPoint = new IPEndPoint(ipAddresses[0], port);

using (client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP))

{

string fileDir = Path.GetDirectoryName(filePath);

string hash = HashFile(filePath);

byte[] fileInfo = GetFileInfoBytes(filePath, hash);

byte[] filePositionBytes = new byte[8];

client.BeginConnect(endPoint, ae.End(), null);

yield return 1;

client.EndConnect(ae.DequeueAsyncResult());

client.BeginSend(fileInfo, 0, fileInfo.Length, SocketFlags.None, ae.End(), null);

yield return 1;

int bytesSent = client.EndSend(ae.DequeueAsyncResult());

client.BeginReceive(filePositionBytes, 0, filePositionBytes.Length, SocketFlags.None, ae.End(), null);

yield return 1;

int bytesReceived = client.EndReceive(ae.DequeueAsyncResult());

Int64 filePosition = 0;

if (bytesReceived == 8)

{

filePosition = BitConverter.ToInt64(filePositionBytes, 0);

Console.WriteLine("Got the file start position: " + filePosition);

}

Int64 bytesToSend = 0;

using (FileStream fs = File.OpenRead(filePath))

{

Byte[] fileBytes;

bytesToSend = fs.Length - filePosition;

fileBytes = new Byte[Properties.Settings.Default.MaxBufferSize];

if (fs.CanSeek)

fs.Seek(filePosition, SeekOrigin.Begin);

while (bytesToSend != 0)

{

if (bytesToSend < fileBytes.Length)

fileBytes = new Byte[bytesToSend];

for (int bytesReadSoFar = 0; bytesReadSoFar < fileBytes.Length; )

{

int bytesReadThisTime = fs.Read(fileBytes, bytesReadSoFar, fileBytes.Length - bytesReadSoFar);

bytesReadSoFar += bytesReadThisTime;

}

client.BeginSend(fileBytes, 0, fileBytes.Length, SocketFlags.None, ae.End(), null);

yield return 1;

bytesToSend -= client.EndSend(ae.DequeueAsyncResult());

}

}

client.BeginDisconnect(true, ae.End(), null);

yield return 1;

client.EndDisconnect(ae.DequeueAsyncResult());

Console.WriteLine("Socket Disconnected");

_processingTable.Remove(string.Format("{0}:{1}", hostNameOrAddress, port));

}

}

#endregion

#region IsBusy

public static bool IsBusy(string server, int port)

{

bool isBusy = false;

if (_processingTable.ContainsKey(string.Format("{0}:{1}", server, port)))

isBusy = true;

return isBusy;

}

#endregion

#region GetFileInfoBytes

private static byte[] GetFileInfoBytes(string fileName, string hash)

{

if (!File.Exists(fileName))

{

throw new FileNotFoundException("GetFileInfoBytes cannot find the specified file.");

}

FileInfo fi = new FileInfo(fileName);

byte[] fileNameBytes = Encoding.UTF8.GetBytes(Path.GetFileName(fileName));

byte[] fileNameLen = BitConverter.GetBytes(fileNameBytes.Length);

byte[] hashBytes = Convert.FromBase64String(hash);

byte[] hashLen = BitConverter.GetBytes(hashBytes.Length);

byte[] fileSizeBytes = BitConverter.GetBytes(fi.Length);

Byte[] dataLength = BitConverter.GetBytes(fileNameLen.Length + fileNameBytes.Length + fileSizeBytes.Length + hashLen.Length + hashBytes.Length + 4);

byte[] fileInfo = new byte[fileNameLen.Length + fileNameBytes.Length + fileSizeBytes.Length + hashLen.Length + hashBytes.Length + 4];

Array.Copy(dataLength, fileInfo, dataLength.Length);

Array.Copy(fileNameLen, 0, fileInfo, dataLength.Length, fileNameLen.Length);

Array.Copy(fileNameBytes, 0, fileInfo, dataLength.Length + fileNameLen.Length, fileNameBytes.Length);

Array.Copy(fileSizeBytes, 0, fileInfo, dataLength.Length + fileNameLen.Length + fileNameBytes.Length, fileSizeBytes.Length);

Array.Copy(hashLen, 0, fileInfo, dataLength.Length + fileNameLen.Length + fileNameBytes.Length + fileSizeBytes.Length, hashLen.Length);

Array.Copy(hashBytes, 0, fileInfo, dataLength.Length + fileNameLen.Length + fileNameBytes.Length + fileSizeBytes.Length + hashLen.Length, hashBytes.Length);

return fileInfo;

}

#endregion

#region HashFile

private static string HashFile(string filePath)

{

string hash = string.Empty;

if (File.Exists(filePath + ".sha"))

{

using (StreamReader sr = new StreamReader(filePath + ".sha"))

{

hash = sr.ReadToEnd();

}

}

else

{

hash = SHA256Utils.GenerateSHA256Hash(filePath);

using (StreamWriter sw = new StreamWriter(string.Format("{0}.sha", filePath)))

{

sw.Write(hash);

sw.Flush();

}

}

return hash;

}

#endregion

 

--- In PowerThreading@yahoogroups.com, "Jeffrey Richter (Wintellect LLC)" <JeffreyR@...> wrote:
>
> Send me some code.
>
> --Jeffrey Richter (http://Wintellect .com)
>
> ________________________________
> From: bonneteit ebonnett@...
> Sent: Thursday, August 06, 2009 12:36 PM
> To: PowerThreading@yahoogroups.com PowerThreading@yahoogroups.com
> Subject: [PowerThreading] AsyncEnumerator.BeginExecute question
>
>
>
> I am calling my static class called PowerThreadingSocketClient from a Console app. I call the Start method, just like it shows in the example. From there, I new up an AsyncEnumerator and call BeginExecute passing my Process method in (and a couple of other params). In the Process method, I am transferring a/some large file(s). However, the BeginExecute, being async, returns right away and the Start method ends. This is closing my client socket immediately. I put a Console.Read in there and the file xfers but that isn't going to work in a real situation.
>
> Is there something I'm missing? Do I have to pass in a Socket instead of creating it in the Process method?
>
> TIA,
>
> Evan
>


#571 From: "bonneteit" <ebonnett@...>
Date: Fri Aug 7, 2009 5:32 pm
Subject: Re: AsyncEnumerator.BeginExecute question
bonneteit
Send Email Send Email
 
I see.  Thanks a lot for the answer.  I posted my code but it doesn't contain
the call to Start in the iterator method.  I'll make that change now.

--- In PowerThreading@yahoogroups.com, Nikos Baxevanis <baxevanis@...> wrote:
>
>
> Hi Evan,
>
>
>
> All you need to do is have your Process method call again the static method
that creates the AE.
>
> Since all this is happening on a threadpool thread you may stop the program
anytime by hitting any key.
>
> There is a very good example in
\PowerThreading\PowerThreading-Samples\AsyncEnumerator\TcpServer
>
> You may also look at the following code,
>
>
>
>     internal sealed class Program {
>         private static void Main() {
>             TcpListener listener = new TcpListener(addr, tcpPort);
>             listener.Start();
>
>             ConnectionListener.Start(listener);
>
>             Console.ReadLine(); // Wait for the user to press any key and
exit.
>
>             listener.Stop();
>         }
>
>     }
>
>
>
>     internal static class ConnectionListener {
>         public static void Start(TcpListener listener) {
>             AsyncEnumerator ae = new AsyncEnumerator();
>             ae.BeginExecute(Process(ae,
>                 listener), ae.EndExecute, null);
>         }
>
>         private static IEnumerator<Int32> Process(AsyncEnumerator ae,
TcpListener listener) {
>             listener.BeginAcceptSocket(ae.End(), null);
>             yield return 1;
>
>             Socket socket;
>             try {  socket = listener.EndAcceptSocket(ae.DequeueAsyncResult());
}
>             catch (ObjectDisposedException) { yield break;}
>
>             Start(listener); // Accept another client.
>
>             // You may call sockets BeginXxx, EndXxx methods here using AE.
>             // ...
>         }
>     }
>
>
>
>
>
> -Nikos Baxevanis
>
>
>
> To: PowerThreading@yahoogroups.com
> From: ebonnett@...
> Date: Thu, 6 Aug 2009 19:35:39 +0000
> Subject: [PowerThreading] AsyncEnumerator.BeginExecute question
>
>
>
>
>
> I am calling my static class called PowerThreadingSocketClient from a Console
app. I call the Start method, just like it shows in the example. From there, I
new up an AsyncEnumerator and call BeginExecute passing my Process method in
(and a couple of other params). In the Process method, I am transferring a/some
large file(s). However, the BeginExecute, being async, returns right away and
the Start method ends. This is closing my client socket immediately. I put a
Console.Read in there and the file xfers but that isn't going to work in a real
situation.
>
> Is there something I'm missing? Do I have to pass in a Socket instead of
creating it in the Process method?
>
> TIA,
>
> Evan
>
>
>
>
>
>
>
>
>
> _________________________________________________________________
> Σύρετε φωτογραφίες στο παράθυρο του Messenger. Δείτε πώς.
> http://download.live.com/messenger
>

#572 From: "amaymin" <amaymin@...>
Date: Tue Aug 11, 2009 2:41 pm
Subject: MonitorResourceLock
amaymin
Send Email Send Email
 
Hi, I am stuck on .NET 2.0 and am using this library for a project. I originally
designed around this library because of the ReadWriterLock class as well as the
option to use other locks.

Although I wanted to use a multiple reader, one writer system, the only locks
that worked well for me were the MonitorResourceLocks.

Now, I am getting a strange deadlock case and am wondering if one thread does a
.WaitToRead() and another does a .WaitToWrite() on a MonitorResourceLock, could
they deadlock? Do I need to do only reads or only writes with a
monitorresourcelock?

Thanks,
-Allan

#573 From: "Jeffrey Richter (Wintellect LLC)" <JeffreyR@...>
Date: Tue Aug 11, 2009 3:03 pm
Subject: RE: MonitorResourceLock
jeffrey.richter
Send Email Send Email
 

The MonitorResourecLock is a mutual-exclusive lock and so only 1 thread at a time can own the lock.

The ReaderWriterLock is a reader-writer lock and so multiple readers can get it simultaneously but only one writer at a time can get it.

If a thread is blocked on a WaitToRead/Write call, then some other thread must own the lock and is not releasing it.

 

If one thread calls .WaitToRead and another calls .WaitToWrite, then one of them will get the lock assuming the lock is not owned by another thread.

 

-- Jeffrey Richter (http://Wintellect.com)

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of amaymin
Sent: Tuesday, August 11, 2009 7:41 AM
To: PowerThreading@yahoogroups.com
Subject: [PowerThreading] MonitorResourceLock

 

 

Hi, I am stuck on .NET 2.0 and am using this library for a project. I originally designed around this library because of the ReadWriterLock class as well as the option to use other locks.

Although I wanted to use a multiple reader, one writer system, the only locks that worked well for me were the MonitorResourceLocks.

Now, I am getting a strange deadlock case and am wondering if one thread does a .WaitToRead() and another does a .WaitToWrite() on a MonitorResourceLock, could they deadlock? Do I need to do only reads or only writes with a monitorresourcelock?

Thanks,
-Allan


#574 From: "simonyun" <simonyun@...>
Date: Wed Aug 12, 2009 1:49 pm
Subject: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
simonyun
Send Email Send Email
 
Hi everyone,

I'm trying to use an AsyncEnumerator that's called (ultimately) from an ASP.NET
MVC 2 controller:

AsyncEnumerator<List<string>> ae = new AsyncEnumerator<List<string>>();
List<string> list = ae.EndExecute(ae.BeginExecute(MyEnumerator(ae, "foo bar"),
null));

When I execute this code in a unit test or test console app, it runs fine (it's
being called from the main thread).  However, when I execute it in the web site,
it blocks forever (it's being called from a worker thread).  My enumerator just
never gets called after the yield return 1; it looks like the calls to the
AsyncCallbacks in my async operations within my enumerator are stuck in
sleep/wait/join.  I am sure that all the asynchronous operations I'm performing
within my enumerator are returning properly.

Do I need to do anything special to make this work?  Thanks in advance.

Simon

#575 From: Charles Prakash Dasari <prakashd@...>
Date: Wed Aug 12, 2009 4:43 pm
Subject: RE: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
raodcp
Send Email Send Email
 

You seem to be running your calls in the synchronous mode – i.e. not waiting for a callback. You should clear up the sync context on AE if you want to run in the sync mode.

 

The following statement just after creating AE should do:

 

ae.SyncContext = null;

 

Regards,

Prakash

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of simonyun
Sent: Wednesday, August 12, 2009 6:50 AM
To: PowerThreading@yahoogroups.com
Subject: [PowerThreading] AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

 

Hi everyone,

I'm trying to use an AsyncEnumerator that's called (ultimately) from an ASP.NET MVC 2 controller:

AsyncEnumerator<List<string>> ae = new AsyncEnumerator<List<string>>();
List<string> list = ae.EndExecute(ae.BeginExecute(MyEnumerator(ae, "foo bar"), null));

When I execute this code in a unit test or test console app, it runs fine (it's being called from the main thread). However, when I execute it in the web site, it blocks forever (it's being called from a worker thread). My enumerator just never gets called after the yield return 1; it looks like the calls to the AsyncCallbacks in my async operations within my enumerator are stuck in sleep/wait/join. I am sure that all the asynchronous operations I'm performing within my enumerator are returning properly.

Do I need to do anything special to make this work? Thanks in advance.

Simon


#576 From: Charles Prakash Dasari <prakashd@...>
Date: Wed Aug 12, 2009 5:27 pm
Subject: RE: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
raodcp
Send Email Send Email
 

So this brings one question to me: What is the use of copying Thread.CurrentThread.SynchronizationContext to AsyncEnumerator.SyncContext when the passed in callback is null in ae.BeginExecute call?

 

Regards,

Prakash

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of Charles Prakash Dasari
Sent: Wednesday, August 12, 2009 9:44 AM
To: PowerThreading@yahoogroups.com
Subject: RE: [PowerThreading] AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

 

You seem to be running your calls in the synchronous mode – i.e. not waiting for a callback. You should clear up the sync context on AE if you want to run in the sync mode.

 

The following statement just after creating AE should do:

 

ae.SyncContext = null;

 

Regards,

Prakash

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of simonyun
Sent: Wednesday, August 12, 2009 6:50 AM
To: PowerThreading@yahoogroups.com
Subject: [PowerThreading] AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

 

Hi everyone,

I'm trying to use an AsyncEnumerator that's called (ultimately) from an ASP.NET MVC 2 controller:

AsyncEnumerator<List<string>> ae = new AsyncEnumerator<List<string>>();
List<string> list = ae.EndExecute(ae.BeginExecute(MyEnumerator(ae, "foo bar"), null));

When I execute this code in a unit test or test console app, it runs fine (it's being called from the main thread). However, when I execute it in the web site, it blocks forever (it's being called from a worker thread). My enumerator just never gets called after the yield return 1; it looks like the calls to the AsyncCallbacks in my async operations within my enumerator are stuck in sleep/wait/join. I am sure that all the asynchronous operations I'm performing within my enumerator are returning properly.

Do I need to do anything special to make this work? Thanks in advance.

Simon


#577 From: "simonyun" <simonyun@...>
Date: Wed Aug 12, 2009 5:35 pm
Subject: Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
simonyun
Send Email Send Email
 
Thanks for your response.  It fixed my problem.  I was trying to understand why
and found this blog post:
http://www.aaronlerch.com/blog/2007/05/19/net-20-winforms-multithreading-and-a-f\
ew-long-days/

That is very similar to the problem I'm having with the
AspNetSynchronizationContext.  Since there are multiple requests coming in from
the page (Javascript), I think what's happening is that the
AspNetSynchronizationContext referenced by the AE no longer has a message loop,
meaning that the callback to my enumerator never gets called.  Setting
ae.SyncContext = null; fixes the problem ... and I don't care about the callback
thread in this case so it's fine.

I think I would still have the same problem if I were using the AE
asynchronously here.

If any of my reasoning is incorrect, please let me know.

Simon

PS - I hate that I'm calling this synchronously ... it's just a temporary
measure until I can convert some more of the surrounding code to the async
pattern.

--- In PowerThreading@yahoogroups.com, Charles Prakash Dasari <prakashd@...>
wrote:
>
> You seem to be running your calls in the synchronous mode - i.e. not waiting
for a callback. You should clear up the sync context on AE if you want to run in
the sync mode.
>
> The following statement just after creating AE should do:
>
> ae.SyncContext = null;
>
> Regards,
> Prakash
>
> From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com]
On Behalf Of simonyun
> Sent: Wednesday, August 12, 2009 6:50 AM
> To: PowerThreading@yahoogroups.com
> Subject: [PowerThreading] AsyncEnumerator blocking forever when called sync
from ASP.NET MVC 2 controller
>
>
>
> Hi everyone,
>
> I'm trying to use an AsyncEnumerator that's called (ultimately) from an
ASP.NET MVC 2 controller:
>
> AsyncEnumerator<List<string>> ae = new AsyncEnumerator<List<string>>();
> List<string> list = ae.EndExecute(ae.BeginExecute(MyEnumerator(ae, "foo bar"),
null));
>
> When I execute this code in a unit test or test console app, it runs fine
(it's being called from the main thread). However, when I execute it in the web
site, it blocks forever (it's being called from a worker thread). My enumerator
just never gets called after the yield return 1; it looks like the calls to the
AsyncCallbacks in my async operations within my enumerator are stuck in
sleep/wait/join. I am sure that all the asynchronous operations I'm performing
within my enumerator are returning properly.
>
> Do I need to do anything special to make this work? Thanks in advance.
>
> Simon
>

#578 From: "simonyun" <simonyun@...>
Date: Wed Aug 12, 2009 5:37 pm
Subject: Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
simonyun
Send Email Send Email
 
I think the answer to your question is that even if the AE is being called
synchronously, the *enumerator* is performing async operations and needs to be
called back into (by the callback returned from ae.End()).  So you'd still, in
UI cases, want the enumerator to be called by the UI thread.

Simon

--- In PowerThreading@yahoogroups.com, Charles Prakash Dasari <prakashd@...>
wrote:
>
> So this brings one question to me: What is the use of copying
Thread.CurrentThread.SynchronizationContext to AsyncEnumerator.SyncContext when
the passed in callback is null in ae.BeginExecute call?
>
> Regards,
> Prakash
>
> From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com]
On Behalf Of Charles Prakash Dasari
> Sent: Wednesday, August 12, 2009 9:44 AM
> To: PowerThreading@yahoogroups.com
> Subject: RE: [PowerThreading] AsyncEnumerator blocking forever when called
sync from ASP.NET MVC 2 controller
>
>
> You seem to be running your calls in the synchronous mode - i.e. not waiting
for a callback. You should clear up the sync context on AE if you want to run in
the sync mode.
>
> The following statement just after creating AE should do:
>
> ae.SyncContext = null;
>
> Regards,
> Prakash
>
> From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com]
On Behalf Of simonyun
> Sent: Wednesday, August 12, 2009 6:50 AM
> To: PowerThreading@yahoogroups.com
> Subject: [PowerThreading] AsyncEnumerator blocking forever when called sync
from ASP.NET MVC 2 controller
>
>
>
> Hi everyone,
>
> I'm trying to use an AsyncEnumerator that's called (ultimately) from an
ASP.NET MVC 2 controller:
>
> AsyncEnumerator<List<string>> ae = new AsyncEnumerator<List<string>>();
> List<string> list = ae.EndExecute(ae.BeginExecute(MyEnumerator(ae, "foo bar"),
null));
>
> When I execute this code in a unit test or test console app, it runs fine
(it's being called from the main thread). However, when I execute it in the web
site, it blocks forever (it's being called from a worker thread). My enumerator
just never gets called after the yield return 1; it looks like the calls to the
AsyncCallbacks in my async operations within my enumerator are stuck in
sleep/wait/join. I am sure that all the asynchronous operations I'm performing
within my enumerator are returning properly.
>
> Do I need to do anything special to make this work? Thanks in advance.
>
> Simon
>

#579 From: Charles Prakash Dasari <prakashd@...>
Date: Wed Aug 12, 2009 7:58 pm
Subject: RE: Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
raodcp
Send Email Send Email
 

Yes you are right …

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of simonyun
Sent: Wednesday, August 12, 2009 10:38 AM
To: PowerThreading@yahoogroups.com
Subject: [PowerThreading] Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

 

I think the answer to your question is that even if the AE is being called synchronously, the *enumerator* is performing async operations and needs to be called back into (by the callback returned from ae.End()). So you'd still, in UI cases, want the enumerator to be called by the UI thread.

Simon

--- In PowerThreading@yahoogroups.com, Charles Prakash Dasari <prakashd@...> wrote:
>
> So this brings one question to me: What is the use of copying Thread.CurrentThread.SynchronizationContext to AsyncEnumerator.SyncContext when the passed in callback is null in ae.BeginExecute call?
>
> Regards,
> Prakash
>
> From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of Charles Prakash Dasari
> Sent: Wednesday, August 12, 2009 9:44 AM
> To: PowerThreading@yahoogroups.com
> Subject: RE: [PowerThreading] AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
>
>
> You seem to be running your calls in the synchronous mode - i.e. not waiting for a callback. You should clear up the sync context on AE if you want to run in the sync mode.
>
> The following statement just after creating AE should do:
>
> ae.SyncContext = null;
>
> Regards,
> Prakash
>
> From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of simonyun
> Sent: Wednesday, August 12, 2009 6:50 AM
> To: PowerThreading@yahoogroups.com
> Subject: [PowerThreading] AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
>
>
>
> Hi everyone,
>
> I'm trying to use an AsyncEnumerator that's called (ultimately) from an ASP.NET MVC 2 controller:
>
> AsyncEnumerator<List<string>> ae = new AsyncEnumerator<List<string>>();
> List<string> list = ae.EndExecute(ae.BeginExecute(MyEnumerator(ae, "foo bar"), null));
>
> When I execute this code in a unit test or test console app, it runs fine (it's being called from the main thread). However, when I execute it in the web site, it blocks forever (it's being called from a worker thread). My enumerator just never gets called after the yield return 1; it looks like the calls to the AsyncCallbacks in my async operations within my enumerator are stuck in sleep/wait/join. I am sure that all the asynchronous operations I'm performing within my enumerator are returning properly.
>
> Do I need to do anything special to make this work? Thanks in advance.
>
> Simon
>


#580 From: Charles Prakash Dasari <prakashd@...>
Date: Wed Aug 12, 2009 8:00 pm
Subject: RE: Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
raodcp
Send Email Send Email
 

I think it is about a deadlock. The call to ae.EndExecute would have blocked the thread with a wait and the callback is waiting to be executed on this same thread. The EndExecute wouldn’t proceed further until the callback is finished. So this creates a deadlock.

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of simonyun
Sent: Wednesday, August 12, 2009 10:35 AM
To: PowerThreading@yahoogroups.com
Subject: [PowerThreading] Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

 

Thanks for your response. It fixed my problem. I was trying to understand why and found this blog post: http://www.aaronlerch.com/blog/2007/05/19/net-20-winforms-multithreading-and-a-few-long-days/

That is very similar to the problem I'm having with the AspNetSynchronizationContext. Since there are multiple requests coming in from the page (Javascript), I think what's happening is that the AspNetSynchronizationContext referenced by the AE no longer has a message loop, meaning that the callback to my enumerator never gets called. Setting ae.SyncContext = null; fixes the problem ... and I don't care about the callback thread in this case so it's fine.

I think I would still have the same problem if I were using the AE asynchronously here.

If any of my reasoning is incorrect, please let me know.

Simon

PS - I hate that I'm calling this synchronously ... it's just a temporary measure until I can convert some more of the surrounding code to the async pattern.

--- In PowerThreading@yahoogroups.com, Charles Prakash Dasari <prakashd@...> wrote:
>
> You seem to be running your calls in the synchronous mode - i.e. not waiting for a callback. You should clear up the sync context on AE if you want to run in the sync mode.
>
> The following statement just after creating AE should do:
>
> ae.SyncContext = null;
>
> Regards,
> Prakash
>
> From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of simonyun
> Sent: Wednesday, August 12, 2009 6:50 AM
> To: PowerThreading@yahoogroups.com
> Subject: [PowerThreading] AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
>
>
>
> Hi everyone,
>
> I'm trying to use an AsyncEnumerator that's called (ultimately) from an ASP.NET MVC 2 controller:
>
> AsyncEnumerator<List<string>> ae = new AsyncEnumerator<List<string>>();
> List<string> list = ae.EndExecute(ae.BeginExecute(MyEnumerator(ae, "foo bar"), null));
>
> When I execute this code in a unit test or test console app, it runs fine (it's being called from the main thread). However, when I execute it in the web site, it blocks forever (it's being called from a worker thread). My enumerator just never gets called after the yield return 1; it looks like the calls to the AsyncCallbacks in my async operations within my enumerator are stuck in sleep/wait/join. I am sure that all the asynchronous operations I'm performing within my enumerator are returning properly.
>
> Do I need to do anything special to make this work? Thanks in advance.
>
> Simon
>


#581 From: "Jeffrey Richter (Wintellect LLC)" <JeffreyR@...>
Date: Thu Aug 13, 2009 1:26 am
Subject: RE: Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
jeffrey.richter
Send Email Send Email
 

Yes, you are exactly right.

 

The biggest problem people have the AE is this deadlock that occurs in some situation due to the SynchronizationContext.

So, I’ve been thinking…

 

What if, in the next version, I always default an AE’s SyncContext to null and force people to set it if they want it set.

This way, the deadlock problem goes away but this is a breaking change.

 

However, a new problem now arises: in a Windows Forms/WPF app, an exception will occur if you attempt to update the UI controls from a thread pool thread. How, the fix for this is easy: just set SyncConext to SynchronizationContext.Current before calling BeginXxx.

 

Also, in an ASP.NET app, the culture and principle information will not flow to other thread pool threads automatically unless you explicitly set the SyncContext property but I’m not sure how many people care about this anyway so I think it will break fewer people and it will actually improve performance some.

 

If I made this breaking change, would this really become a big problem for anyone? If so, please let me know.

If anyone has a suggestion for how I can fix this without a breaking change, let me know.

I really want to do something to stop these problems.

 

Thanks,
-- Jeffrey Richter (http://Wintellect.com)

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of Charles Prakash Dasari
Sent: Wednesday, August 12, 2009 1:01 PM
To: PowerThreading@yahoogroups.com
Subject: RE: [PowerThreading] Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

 

I think it is about a deadlock. The call to ae.EndExecute would have blocked the thread with a wait and the callback is waiting to be executed on this same thread. The EndExecute wouldn’t proceed further until the callback is finished. So this creates a deadlock.

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of simonyun
Sent: Wednesday, August 12, 2009 10:35 AM
To: PowerThreading@yahoogroups.com
Subject: [PowerThreading] Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

 

Thanks for your response. It fixed my problem. I was trying to understand why and found this blog post: http://www.aaronlerch.com/blog/2007/05/19/net-20-winforms-multithreading-and-a-few-long-days/

That is very similar to the problem I'm having with the AspNetSynchronizationContext. Since there are multiple requests coming in from the page (Javascript), I think what's happening is that the AspNetSynchronizationContext referenced by the AE no longer has a message loop, meaning that the callback to my enumerator never gets called. Setting ae.SyncContext = null; fixes the problem ... and I don't care about the callback thread in this case so it's fine.

I think I would still have the same problem if I were using the AE asynchronously here.

If any of my reasoning is incorrect, please let me know.

Simon

PS - I hate that I'm calling this synchronously ... it's just a temporary measure until I can convert some more of the surrounding code to the async pattern.

--- In PowerThreading@yahoogroups.com, Charles Prakash Dasari <prakashd@...> wrote:
>
> You seem to be running your calls in the synchronous mode - i.e. not waiting for a callback. You should clear up the sync context on AE if you want to run in the sync mode.
>
> The following statement just after creating AE should do:
>
> ae.SyncContext = null;
>
> Regards,
> Prakash
>
> From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of simonyun
> Sent: Wednesday, August 12, 2009 6:50 AM
> To: PowerThreading@yahoogroups.com
> Subject: [PowerThreading] AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
>
>
>
> Hi everyone,
>
> I'm trying to use an AsyncEnumerator that's called (ultimately) from an ASP.NET MVC 2 controller:
>
> AsyncEnumerator<List<string>> ae = new AsyncEnumerator<List<string>>();
> List<string> list = ae.EndExecute(ae.BeginExecute(MyEnumerator(ae, "foo bar"), null));
>
> When I execute this code in a unit test or test console app, it runs fine (it's being called from the main thread). However, when I execute it in the web site, it blocks forever (it's being called from a worker thread). My enumerator just never gets called after the yield return 1; it looks like the calls to the AsyncCallbacks in my async operations within my enumerator are stuck in sleep/wait/join. I am sure that all the asynchronous operations I'm performing within my enumerator are returning properly.
>
> Do I need to do anything special to make this work? Thanks in advance.
>
> Simon
>


#582 From: Charles Prakash Dasari <prakashd@...>
Date: Thu Aug 13, 2009 2:02 am
Subject: RE: Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
raodcp
Send Email Send Email
 

I don’t think you should make the breaking change. The problem will be when people are using libraries which use AE, and if they need the context to be maintained and the default is changed not to copy then it will be a problem.

 

I’d suggest another constructor with a flag to do that, such as AsyncEnumerator(bool emptySyncContext) – something like that… with the default maintaining current behavior.

 

What I am using in my code right now is this:

 

SynchronizationContext saved = SynchronizationContext.Current;

try

{

  SynchronizationContext.Current = null;

  AsyncEnumerator ae = new AsyncEnumerator();

  ae.EndExecute(ae.BeginExecute(…………………..));

}

finally

{

  SynchronizationContext.Current = saved;

}

 

This is will allow all the AE’s that are created down the chain also to have a null sync context and thus make sure there won’t be any deadlock when I initiated the operation in a sync-mode!

 

Regards,

Prakash

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of Jeffrey Richter (Wintellect LLC)
Sent: Wednesday, August 12, 2009 6:27 PM
To: PowerThreading@yahoogroups.com
Subject: RE: [PowerThreading] Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

 

Yes, you are exactly right.

 

The biggest problem people have the AE is this deadlock that occurs in some situation due to the SynchronizationContext.

So, I’ve been thinking…

 

What if, in the next version, I always default an AE’s SyncContext to null and force people to set it if they want it set.

This way, the deadlock problem goes away but this is a breaking change.

 

However, a new problem now arises: in a Windows Forms/WPF app, an exception will occur if you attempt to update the UI controls from a thread pool thread. How, the fix for this is easy: just set SyncConext to SynchronizationContext.Current before calling BeginXxx.

 

Also, in an ASP.NET app, the culture and principle information will not flow to other thread pool threads automatically unless you explicitly set the SyncContext property but I’m not sure how many people care about this anyway so I think it will break fewer people and it will actually improve performance some.

 

If I made this breaking change, would this really become a big problem for anyone? If so, please let me know.

If anyone has a suggestion for how I can fix this without a breaking change, let me know.

I really want to do something to stop these problems.

 

Thanks,
-- Jeffrey Richter (
http://Wintellect.com)

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of Charles Prakash Dasari
Sent: Wednesday, August 12, 2009 1:01 PM
To: PowerThreading@yahoogroups.com
Subject: RE: [PowerThreading] Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

 

I think it is about a deadlock. The call to ae.EndExecute would have blocked the thread with a wait and the callback is waiting to be executed on this same thread. The EndExecute wouldn’t proceed further until the callback is finished. So this creates a deadlock.

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of simonyun
Sent: Wednesday, August 12, 2009 10:35 AM
To: PowerThreading@yahoogroups.com
Subject: [PowerThreading] Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

 

Thanks for your response. It fixed my problem. I was trying to understand why and found this blog post: http://www.aaronlerch.com/blog/2007/05/19/net-20-winforms-multithreading-and-a-few-long-days/

That is very similar to the problem I'm having with the AspNetSynchronizationContext. Since there are multiple requests coming in from the page (Javascript), I think what's happening is that the AspNetSynchronizationContext referenced by the AE no longer has a message loop, meaning that the callback to my enumerator never gets called. Setting ae.SyncContext = null; fixes the problem ... and I don't care about the callback thread in this case so it's fine.

I think I would still have the same problem if I were using the AE asynchronously here.

If any of my reasoning is incorrect, please let me know.

Simon

PS - I hate that I'm calling this synchronously ... it's just a temporary measure until I can convert some more of the surrounding code to the async pattern.

--- In PowerThreading@yahoogroups.com, Charles Prakash Dasari <prakashd@...> wrote:
>
> You seem to be running your calls in the synchronous mode - i.e. not waiting for a callback. You should clear up the sync context on AE if you want to run in the sync mode.
>
> The following statement just after creating AE should do:
>
> ae.SyncContext = null;
>
> Regards,
> Prakash
>
> From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of simonyun
> Sent: Wednesday, August 12, 2009 6:50 AM
> To: PowerThreading@yahoogroups.com
> Subject: [PowerThreading] AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
>
>
>
> Hi everyone,
>
> I'm trying to use an AsyncEnumerator that's called (ultimately) from an ASP.NET MVC 2 controller:
>
> AsyncEnumerator<List<string>> ae = new AsyncEnumerator<List<string>>();
> List<string> list = ae.EndExecute(ae.BeginExecute(MyEnumerator(ae, "foo bar"), null));
>
> When I execute this code in a unit test or test console app, it runs fine (it's being called from the main thread). However, when I execute it in the web site, it blocks forever (it's being called from a worker thread). My enumerator just never gets called after the yield return 1; it looks like the calls to the AsyncCallbacks in my async operations within my enumerator are stuck in sleep/wait/join. I am sure that all the asynchronous operations I'm performing within my enumerator are returning properly.
>
> Do I need to do anything special to make this work? Thanks in advance.
>
> Simon
>


#583 From: Nikos Baxevanis <baxevanis@...>
Date: Thu Aug 13, 2009 6:24 am
Subject: RE: Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
n.baxevanis
Send Email Send Email
 
Hi Prakash,
About the overload that accepts a Boolean, keep in mind that there is an overload already that accepts a String. Having another overload that accepts a Boolean you add complexity to the API because it has an impact on how things go (SyncContext).
I think in some future version AE should set SyncContext to null by default.
 

To: PowerThreading@yahoogroups.com
From: prakashd@...
Date: Wed, 12 Aug 2009 19:02:16 -0700
Subject: RE: [PowerThreading] Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

I don't think you should make the breaking change. The problem will be when people are using libraries which use AE, and if they need the context to be maintained and the default is changed not to copy then it will be a problem.

 

I'd suggest another constructor with a flag to do that, such as AsyncEnumerator(bool emptySyncContext) - something like that. with the default maintaining current behavior.

 

What I am using in my code right now is this:

 

SynchronizationContext saved = SynchronizationContext.Current;

try

{

  SynchronizationContext.Current = null;

  AsyncEnumerator ae = new AsyncEnumerator();

  ae.EndExecute(ae.BeginExecute(.........));

}

finally

{

  SynchronizationContext.Current = saved;

}

 

This is will allow all the AE's that are created down the chain also to have a null sync context and thus make sure there won't be any deadlock when I initiated the operation in a sync-mode!

 

Regards,

Prakash

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of Jeffrey Richter (Wintellect LLC)
Sent: Wednesday, August 12, 2009 6:27 PM
To: PowerThreading@yahoogroups.com
Subject: RE: [PowerThreading] Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

 

Yes, you are exactly right.

 

The biggest problem people have the AE is this deadlock that occurs in some situation due to the SynchronizationContext.

So, I've been thinking.

 

What if, in the next version, I always default an AE's SyncContext to null and force people to set it if they want it set.

This way, the deadlock problem goes away but this is a breaking change.

 

However, a new problem now arises: in a Windows Forms/WPF app, an exception will occur if you attempt to update the UI controls from a thread pool thread. How, the fix for this is easy: just set SyncConext to SynchronizationContext.Current before calling BeginXxx.

 

Also, in an ASP.NET app, the culture and principle information will not flow to other thread pool threads automatically unless you explicitly set the SyncContext property but I'm not sure how many people care about this anyway so I think it will break fewer people and it will actually improve performance some.

 

If I made this breaking change, would this really become a big problem for anyone? If so, please let me know.

If anyone has a suggestion for how I can fix this without a breaking change, let me know.

I really want to do something to stop these problems.

 

Thanks,
-- Jeffrey Richter (
http://Wintellect.com)

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of Charles Prakash Dasari
Sent: Wednesday, August 12, 2009 1:01 PM
To: PowerThreading@yahoogroups.com
Subject: RE: [PowerThreading] Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

 

I think it is about a deadlock. The call to ae.EndExecute would have blocked the thread with a wait and the callback is waiting to be executed on this same thread. The EndExecute wouldn't proceed further until the callback is finished. So this creates a deadlock.

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of simonyun
Sent: Wednesday, August 12, 2009 10:35 AM
To: PowerThreading@yahoogroups.com
Subject: [PowerThreading] Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

 

Thanks for your response. It fixed my problem. I was trying to understand why and found this blog post: http://www.aaronlerch.com/blog/2007/05/19/net-20-winforms-multithreading-and-a-few-long-days/

That is very similar to the problem I'm having with the AspNetSynchronizationContext. Since there are multiple requests coming in from the page (Javascript), I think what's happening is that the AspNetSynchronizationContext referenced by the AE no longer has a message loop, meaning that the callback to my enumerator never gets called. Setting ae.SyncContext = null; fixes the problem ... and I don't care about the callback thread in this case so it's fine.

I think I would still have the same problem if I were using the AE asynchronously here.

If any of my reasoning is incorrect, please let me know.

Simon

PS - I hate that I'm calling this synchronously ... it's just a temporary measure until I can convert some more of the surrounding code to the async pattern.

--- In PowerThreading@yahoogroups.com, Charles Prakash Dasari <prakashd@...> wrote:
>
> You seem to be running your calls in the synchronous mode - i.e. not waiting for a callback. You should clear up the sync context on AE if you want to run in the sync mode.
>
> The following statement just after creating AE should do:
>
> ae.SyncContext = null;
>
> Regards,
> Prakash
>
> From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of simonyun
> Sent: Wednesday, August 12, 2009 6:50 AM
> To: PowerThreading@yahoogroups.com
> Subject: [PowerThreading] AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
>
>
>
> Hi everyone,
>
> I'm trying to use an AsyncEnumerator that's called (ultimately) from an ASP.NET MVC 2 controller:
>
> AsyncEnumerator<List<string>> ae = new AsyncEnumerator<List<string>>();
> List<string> list = ae.EndExecute(ae.BeginExecute(MyEnumerator(ae, "foo bar"), null));
>
> When I execute this code in a unit test or test console app, it runs fine (it's being called from the main thread). However, when I execute it in the web site, it blocks forever (it's being called from a worker thread). My enumerator just never gets called after the yield return 1; it looks like the calls to the AsyncCallbacks in my async operations within my enumerator are stuck in sleep/wait/join. I am sure that all the asynchronous operations I'm performing within my enumerator are returning properly.
>
> Do I need to do anything special to make this work? Thanks in advance.
>
> Simon
>




Μοιραστείτε τις αναμνήσεις σας μέσω Internet με τους φίλους σας με τους φίλους σας.

#584 From: "Jeffrey Richter (Wintellect LLC)" <JeffreyR@...>
Date: Thu Aug 13, 2009 2:57 pm
Subject: RE: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
jeffrey.richter
Send Email Send Email
 

Short answer: after new’ing up the ae, do this: ae.SyncConext = null;

 

You can search the Yahoo news group for other posts about hanging and SyncContext.

Alternatively, don’t wait for the AE synchronously by calling EndExecute the way you. This kinda defeats the purpose of  using the AE anyway.

 

-- Jeffrey Richter (http://Wintellect.com)

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of simonyun
Sent: Wednesday, August 12, 2009 6:50 AM
To: PowerThreading@yahoogroups.com
Subject: [PowerThreading] AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

 

Hi everyone,

I'm trying to use an AsyncEnumerator that's called (ultimately) from an ASP.NET MVC 2 controller:

AsyncEnumerator<List<string>> ae = new AsyncEnumerator<List<string>>();
List<string> list = ae.EndExecute(ae.BeginExecute(MyEnumerator(ae, "foo bar"), null));

When I execute this code in a unit test or test console app, it runs fine (it's being called from the main thread). However, when I execute it in the web site, it blocks forever (it's being called from a worker thread). My enumerator just never gets called after the yield return 1; it looks like the calls to the AsyncCallbacks in my async operations within my enumerator are stuck in sleep/wait/join. I am sure that all the asynchronous operations I'm performing within my enumerator are returning properly.

Do I need to do anything special to make this work? Thanks in advance.

Simon


#585 From: Charles Prakash Dasari <prakashd@...>
Date: Thu Aug 13, 2009 5:48 pm
Subject: RE: Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
raodcp
Send Email Send Email
 

Well, consider the point where you are working with the code that you don’t own. Let’s say you are using a class written by somebody which exposes an APM method pair. And let’s say that they had implemented this APM method pair using AsyncEnumerator. Now you pass a callback to the begin method in a UI context. Even though you set the SyncContext on your AE, it won’t be useful, since the AE that is used in the other class doesn’t copy it by default (assuming the default behavior is changed).

 

Since nullifying SyncContext is ONLY needed when you call the Begin/End methods in a sync fashion (i.e. not using a callback), I don’t think it should be made a default. Today I use a very nice, simple and easy construct to propagate a null sync context to all the AE’s that might be instantiated down the chain without breaking the default behavior … it goes like this:

 

using (new NullSynchronizationContext())

{

  var ae = new AsyncEnumerator();

  ae.EndExecute(ae.BeginExecute(…));

}

 

This is much, much easier than breaking the current behavior IMO.

 

PS: I can share the code for NullSynchronizationContext if you like!

 

Regards,

Prakash

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of Nikos Baxevanis
Sent: Wednesday, August 12, 2009 11:25 PM
To: PowerThreading yahoogroups
Subject: RE: [PowerThreading] Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

 

Hi Prakash,
About the overload that accepts a Boolean, keep in mind that there is an overload already that accepts a String. Having another overload that accepts a Boolean you add complexity to the API because it has an impact on how things go (SyncContext).
I think in some future version AE should set SyncContext to null by default.
 


To: PowerThreading@yahoogroups.com
From: prakashd@...
Date: Wed, 12 Aug 2009 19:02:16 -0700
Subject: RE: [PowerThreading] Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

I don't think you should make the breaking change. The problem will be when people are using libraries which use AE, and if they need the context to be maintained and the default is changed not to copy then it will be a problem.

 

I'd suggest another constructor with a flag to do that, such as AsyncEnumerator(bool emptySyncContext) - something like that. with the default maintaining current behavior.

 

What I am using in my code right now is this:

 

SynchronizationContext saved = SynchronizationContext.Current;

try

{

  SynchronizationContext.Current = null;

  AsyncEnumerator ae = new AsyncEnumerator();

  ae.EndExecute(ae.BeginExecute(.........));

}

finally

{

  SynchronizationContext.Current = saved;

}

 

This is will allow all the AE's that are created down the chain also to have a null sync context and thus make sure there won't be any deadlock when I initiated the operation in a sync-mode!

 

Regards,

Prakash

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of Jeffrey Richter (Wintellect LLC)
Sent: Wednesday, August 12, 2009 6:27 PM
To: PowerThreading@yahoogroups.com
Subject: RE: [PowerThreading] Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

 

Yes, you are exactly right.

 

The biggest problem people have the AE is this deadlock that occurs in some situation due to the SynchronizationContext.

So, I've been thinking.

 

What if, in the next version, I always default an AE's SyncContext to null and force people to set it if they want it set.

This way, the deadlock problem goes away but this is a breaking change.

 

However, a new problem now arises: in a Windows Forms/WPF app, an exception will occur if you attempt to update the UI controls from a thread pool thread. How, the fix for this is easy: just set SyncConext to SynchronizationContext.Current before calling BeginXxx.

 

Also, in an ASP.NET app, the culture and principle information will not flow to other thread pool threads automatically unless you explicitly set the SyncContext property but I'm not sure how many people care about this anyway so I think it will break fewer people and it will actually improve performance some.

 

If I made this breaking change, would this really become a big problem for anyone? If so, please let me know.

If anyone has a suggestion for how I can fix this without a breaking change, let me know.

I really want to do something to stop these problems.

 

Thanks,
-- Jeffrey Richter (
http://Wintellect.com)

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of Charles Prakash Dasari
Sent: Wednesday, August 12, 2009 1:01 PM
To: PowerThreading@yahoogroups.com
Subject: RE: [PowerThreading] Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

 

I think it is about a deadlock. The call to ae.EndExecute would have blocked the thread with a wait and the callback is waiting to be executed on this same thread. The EndExecute wouldn't proceed further until the callback is finished. So this creates a deadlock.

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of simonyun
Sent: Wednesday, August 12, 2009 10:35 AM
To: PowerThreading@yahoogroups.com
Subject: [PowerThreading] Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

 

Thanks for your response. It fixed my problem. I was trying to understand why and found this blog post: http://www.aaronlerch.com/blog/2007/05/19/net-20-winforms-multithreading-and-a-few-long-days/

That is very similar to the problem I'm having with the AspNetSynchronizationContext. Since there are multiple requests coming in from the page (Javascript), I think what's happening is that the AspNetSynchronizationContext referenced by the AE no longer has a message loop, meaning that the callback to my enumerator never gets called. Setting ae.SyncContext = null; fixes the problem ... and I don't care about the callback thread in this case so it's fine.

I think I would still have the same problem if I were using the AE asynchronously here.

If any of my reasoning is incorrect, please let me know.

Simon

PS - I hate that I'm calling this synchronously ... it's just a temporary measure until I can convert some more of the surrounding code to the async pattern.

--- In PowerThreading@yahoogroups.com, Charles Prakash Dasari <prakashd@...> wrote:
>
> You seem to be running your calls in the synchronous mode - i.e. not waiting for a callback. You should clear up the sync context on AE if you want to run in the sync mode.
>
> The following statement just after creating AE should do:
>
> ae.SyncContext = null;
>
> Regards,
> Prakash
>
> From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of simonyun
> Sent: Wednesday, August 12, 2009 6:50 AM
> To: PowerThreading@yahoogroups.com
> Subject: [PowerThreading] AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
>
>
>
> Hi everyone,
>
> I'm trying to use an AsyncEnumerator that's called (ultimately) from an ASP.NET MVC 2 controller:
>
> AsyncEnumerator<List<string>> ae = new AsyncEnumerator<List<string>>();
> List<string> list = ae.EndExecute(ae.BeginExecute(MyEnumerator(ae, "foo bar"), null));
>
> When I execute this code in a unit test or test console app, it runs fine (it's being called from the main thread). However, when I execute it in the web site, it blocks forever (it's being called from a worker thread). My enumerator just never gets called after the yield return 1; it looks like the calls to the AsyncCallbacks in my async operations within my enumerator are stuck in sleep/wait/join. I am sure that all the asynchronous operations I'm performing within my enumerator are returning properly.
>
> Do I need to do anything special to make this work? Thanks in advance.
>
> Simon
>

 

 


Μοιραστείτε τις αναμνήσεις σας μέσω Internet με τους φίλους σας με τους φίλους σας.


#586 From: "simonyun" <simonyun@...>
Date: Thu Aug 13, 2009 11:26 pm
Subject: Re: FW: Timeouts
simonyun
Send Email Send Email
 
Jeffrey,

Do you have a recommended way to guard against the race condition you describe
below?  I want to use an async enumerator to first execute one async operation
with a timeout, followed by several operations in parallel with a different
timeout value.

I'm worried about the race condition since it could prevent subsequent
operations from being processed properly because IsCanceled() will return true
as a result of the first timer's expiration before the second call to
SetCancelTimeout() can be made.

Thanks,
Simon

--- In PowerThreading@yahoogroups.com, "Jeffrey Richter (Wintellect LLC)"
<JeffreyR@...> wrote:
>
> Well, I got free minute and I looked at my code...Good news: I already do what
you want.
> Yes, you can periodically call SetCancelTimeout. When you do, I dispose of the
current timer, and if you don't pass Timeout.Infinite (-1), then I create a new
Timer that goes off when you want it to.
> Note, that there may be a race condition though: after a yield return, your
iterator code may be executing and the current timer could go off before you
call SetCancelTimeout.
> If this happens, then the next time, you call yield return, I will call back
into your code immediately and IsCanceled will return true.
>
> -- Jeffrey Richter (http://Wintellect.com<http://wintellect.com/>)
>
> From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com]
On Behalf Of jon_reis
> Sent: Tuesday, February 17, 2009 9:58 AM
> To: PowerThreading@yahoogroups.com
> Subject: [PowerThreading] Re: FW: Timeouts
>
>
> Hi Jeffrey, thanks for taking the time to help me out.
>
> I tried your suggestion to implement my own EndExecute function to handle
exceptions thrown by Process and this works nicely. Thank you.
>
> I tried your suggestion of using the overloaded ae.End() that takes a dicard
group. I am using ae.End(0, c => null) everywhere since I don't need to do
anything special to clean up. Is this OK, or should I be doing something else?
>
> I tried your suggestion of using a DiscardGroup, but I'm still a little
confused as to how these function. The code as I have it below does not work
properly. It seems the DiscardGroup remembers that group 0, has been discarded
and causes the call to //(1) to be discarded during the second iteration of the
while loop. Am I supposed to increment the DiscardGroup each time I use it up to
a maximum of 64? Besides being pretty combersome, it will only allow me to
receive 64 messages before I run out of DiscardGroups. I don't understand the
usecase for DiscardGroup, what I really want is a DiscardPending that throws out
all pending operations. I'm sure like the other things I have run into that I
must be missing something here.
>
> In your original response you state:
>
> [JR] No. SetCancelTimeout applies to the entire AE object. That is, you are
cancelling the whole workflow, not just a part of it.
>
> I do want to cancel the entire workflow, but I want to change the timeout for
each operation. Like:
>
> ae.SetCancelTimeout(60000,null); // read for 60 seconds
> stream.BeginRead(bbuffer.Array, bbuffer.Length, bbuffer.SpaceAvailable,
ae.End(0, c => null), null);
> yeild 1;
> ae.SetCancelTimeout(-1,null); // turn off cancel
> if(ae.IsCanceled()) yield break;
>
> Will the second call to SetCancelTimout disable the timeout?
>
>
>
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>
>  private void Start()
>     {
>       AsyncEnumerator ae = new AsyncEnumerator();
>       ae.BeginExecute(Process(ae, _listener), EndExecute, ae);
>     }
>
>     private void EndExecute(IAsyncResult result)
>     {
>       try
>       {
>         AsyncEnumerator ae = (AsyncEnumerator)result.AsyncState;
>         ae.EndExecute(result);
>       }
>       catch(Exception ex)
>       {
>         if(OnException != null) OnException(this, ex);
>       }
>     }
>
>     private IEnumerator<Int32> Process(AsyncEnumerator ae, TcpListener server)
>     {
>       server.BeginAcceptTcpClient(ae.End(0,c=>null), null);
>       yield return 1;
>
>       if(_isExiting)
>         yield break;
>
>       using(TcpClient client =
server.EndAcceptTcpClient(ae.DequeueAsyncResult()))
>       {
>         int timeout = 60000;
>         Start();  // Accept another client
>         using(Stream stream = client.GetStream())
>         {
>           CountdownTimer countdownTimer = new CountdownTimer();
>           Buffer<byte> bbuffer = new Buffer<byte>();
>           while(true)
>           {
>             bbuffer.SpaceAvailable += 64 * 1024;
>             stream.BeginRead(bbuffer.Array, bbuffer.Length,
bbuffer.SpaceAvailable, ae.End(0, c => null), null); //(1)
>             countdownTimer.BeginCountdown(timeout, ae.End(0, c=>null), ae);
>             yield return 1;
>
>             timeout = 5000;
>             if(countdownTimer.Expired) // I added this method to the timer you
gave me
>             {
>               ae.DiscardGroup(0);
>               break;
>             }
>             int result = stream.EndRead(ae.DequeueAsyncResult());
>             ae.DiscardGroup(0);
>
>             if(result == 0) break; //client shutdown
>             bbuffer.Length += result;
>             if(bbuffer.Array.ReverseFind(0, bbuffer.Length,
_framing.EndFrameBytes) >= 0) // look for end of message marker
>             {
>               // Write outputData back to client
>               stream.BeginWrite(bbuffer.Array, 0, bbuffer.Length, ae.End(0, c
=> null), null);
>               yield return 1;
>
>               stream.EndWrite(ae.DequeueAsyncResult());
>               bbuffer.Length = 0;
>               timeout = 60000; // wait longer for the start of the next
message
>             }
>           }
>         }
>       }
>    }
>

#587 From: "simonyun" <simonyun@...>
Date: Thu Aug 13, 2009 11:33 pm
Subject: Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
simonyun
Send Email Send Email
 
Jeffrey,

Calling the AE synchronously was just a temporary measure until I could convert
more of the surrounding code to the APM.  And there's a lot of it to convert.

If I set the SyncContext property to null, am I still guaranteed to have only
one thread executing inside the iterator at once?  I'm assuming that if
SyncContext is null, the callback can happen on any ThreadPool thread; I'm not
sure if this means that multiple callbacks can now happen at once since they're
not all necessarily being dispatched to the same thread (as far as I know).

Thanks,
Simon

--- In PowerThreading@yahoogroups.com, "Jeffrey Richter (Wintellect LLC)"
<JeffreyR@...> wrote:
>
> Short answer: after new'ing up the ae, do this: ae.SyncConext = null;
>
> You can search the Yahoo news group for other posts about hanging and
SyncContext.
> Alternatively, don't wait for the AE synchronously by calling EndExecute the
way you. This kinda defeats the purpose of  using the AE anyway.
>
> -- Jeffrey Richter (http://Wintellect.com<http://wintellect.com/>)
>
> From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com]
On Behalf Of simonyun
> Sent: Wednesday, August 12, 2009 6:50 AM
> To: PowerThreading@yahoogroups.com
> Subject: [PowerThreading] AsyncEnumerator blocking forever when called sync
from ASP.NET MVC 2 controller
>
>
>
> Hi everyone,
>
> I'm trying to use an AsyncEnumerator that's called (ultimately) from an
ASP.NET MVC 2 controller:
>
> AsyncEnumerator<List<string>> ae = new AsyncEnumerator<List<string>>();
> List<string> list = ae.EndExecute(ae.BeginExecute(MyEnumerator(ae, "foo bar"),
null));
>
> When I execute this code in a unit test or test console app, it runs fine
(it's being called from the main thread). However, when I execute it in the web
site, it blocks forever (it's being called from a worker thread). My enumerator
just never gets called after the yield return 1; it looks like the calls to the
AsyncCallbacks in my async operations within my enumerator are stuck in
sleep/wait/join. I am sure that all the asynchronous operations I'm performing
within my enumerator are returning properly.
>
> Do I need to do anything special to make this work? Thanks in advance.
>
> Simon
>

#588 From: "Jeffrey Richter (Wintellect LLC)" <JeffreyR@...>
Date: Fri Aug 14, 2009 3:40 am
Subject: RE: Re: FW: Timeouts
jeffrey.richter
Send Email Send Email
 

If you want to execute the first operation without a timeout at all, then just don’t call SetCancelTimeout until after it competes before you initiate the parallel operations.

-- Jeffrey Richter (http://Wintellect.com)

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of simonyun
Sent: Thursday, August 13, 2009 4:26 PM
To: PowerThreading@yahoogroups.com
Subject: [PowerThreading] Re: FW: Timeouts

 

 

Jeffrey,

Do you have a recommended way to guard against the race condition you describe below? I want to use an async enumerator to first execute one async operation with a timeout, followed by several operations in parallel with a different timeout value.

I'm worried about the race condition since it could prevent subsequent operations from being processed properly because IsCanceled() will return true as a result of the first timer's expiration before the second call to SetCancelTimeout() can be made.

Thanks,
Simon

--- In PowerThreading@yahoogroups.com, "Jeffrey Richter (Wintellect LLC)" <JeffreyR@...> wrote:
>
> Well, I got free minute and I looked at my code...Good news: I already do what you want.
> Yes, you can periodically call SetCancelTimeout. When you do, I dispose of the current timer, and if you don't pass Timeout.Infinite (-1), then I create a new Timer that goes off when you want it to.
> Note, that there may be a race condition though: after a yield return, your iterator code may be executing and the current timer could go off before you call SetCancelTimeout.
> If this happens, then the next time, you call yield return, I will call back into your code immediately and IsCanceled will return true.
>
> -- Jeffrey Richter (http://Wintellect.com<http://wintellect.com/>)
>
> From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of jon_reis
> Sent: Tuesday, February 17, 2009 9:58 AM
> To: PowerThreading@yahoogroups.com
> Subject: [PowerThreading] Re: FW: Timeouts
>
>
> Hi Jeffrey, thanks for taking the time to help me out.
>
> I tried your suggestion to implement my own EndExecute function to handle exceptions thrown by Process and this works nicely. Thank you.
>
> I tried your suggestion of using the overloaded ae.End() that takes a dicard group. I am using ae.End(0, c => null) everywhere since I don't need to do anything special to clean up. Is this OK, or should I be doing something else?
>
> I tried your suggestion of using a DiscardGroup, but I'm still a little confused as to how these function. The code as I have it below does not work properly. It seems the DiscardGroup remembers that group 0, has been discarded and causes the call to //(1) to be discarded during the second iteration of the while loop. Am I supposed to increment the DiscardGroup each time I use it up to a maximum of 64? Besides being pretty combersome, it will only allow me to receive 64 messages before I run out of DiscardGroups. I don't understand the usecase for DiscardGroup, what I really want is a DiscardPending that throws out all pending operations. I'm sure like the other things I have run into that I must be missing something here.
>
> In your original response you state:
>
> [JR] No. SetCancelTimeout applies to the entire AE object. That is, you are cancelling the whole workflow, not just a part of it.
>
> I do want to cancel the entire workflow, but I want to change the timeout for each operation. Like:
>
> ae.SetCancelTimeout(60000,null); // read for 60 seconds
> stream.BeginRead(bbuffer.Array, bbuffer.Length, bbuffer.SpaceAvailable, ae.End(0, c => null), null);
> yeild 1;
> ae.SetCancelTimeout(-1,null); // turn off cancel
> if(ae.IsCanceled()) yield break;
>
> Will the second call to SetCancelTimout disable the timeout?
>
>
>
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>
> private void Start()
> {
> AsyncEnumerator ae = new AsyncEnumerator();
> ae.BeginExecute(Process(ae, _listener), EndExecute, ae);
> }
>
> private void EndExecute(IAsyncResult result)
> {
> try
> {
> AsyncEnumerator ae = (AsyncEnumerator)result.AsyncState;
> ae.EndExecute(result);
> }
> catch(Exception ex)
> {
> if(OnException != null) OnException(this, ex);
> }
> }
>
> private IEnumerator<Int32> Process(AsyncEnumerator ae, TcpListener server)
> {
> server.BeginAcceptTcpClient(ae.End(0,c=>null), null);
> yield return 1;
>
> if(_isExiting)
> yield break;
>
> using(TcpClient client = server.EndAcceptTcpClient(ae.DequeueAsyncResult()))
> {
> int timeout = 60000;
> Start(); // Accept another client
> using(Stream stream = client.GetStream())
> {
> CountdownTimer countdownTimer = new CountdownTimer();
> Buffer<byte> bbuffer = new Buffer<byte>();
> while(true)
> {
> bbuffer.SpaceAvailable += 64 * 1024;
> stream.BeginRead(bbuffer.Array, bbuffer.Length, bbuffer.SpaceAvailable, ae.End(0, c => null), null); //(1)
> countdownTimer.BeginCountdown(timeout, ae.End(0, c=>null), ae);
> yield return 1;
>
> timeout = 5000;
> if(countdownTimer.Expired) // I added this method to the timer you gave me
> {
> ae.DiscardGroup(0);
> break;
> }
> int result = stream.EndRead(ae.DequeueAsyncResult());
> ae.DiscardGroup(0);
>
> if(result == 0) break; //client shutdown
> bbuffer.Length += result;
> if(bbuffer.Array.ReverseFind(0, bbuffer.Length, _framing.EndFrameBytes) >= 0) // look for end of message marker
> {
> // Write outputData back to client
> stream.BeginWrite(bbuffer.Array, 0, bbuffer.Length, ae.End(0, c => null), null);
> yield return 1;
>
> stream.EndWrite(ae.DequeueAsyncResult());
> bbuffer.Length = 0;
> timeout = 60000; // wait longer for the start of the next message
> }
> }
> }
> }
> }
>


#589 From: "Jeffrey Richter (Wintellect LLC)" <JeffreyR@...>
Date: Fri Aug 14, 2009 3:42 am
Subject: RE: Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
jeffrey.richter
Send Email Send Email
 

There is only ever one thread in the iterator at any one time – this is ALWAYS guaranteed.

-- Jeffrey Richter (http://Wintellect.com)

 

From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of simonyun
Sent: Thursday, August 13, 2009 4:33 PM
To: PowerThreading@yahoogroups.com
Subject: [PowerThreading] Re: AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller

 

 

Jeffrey,

Calling the AE synchronously was just a temporary measure until I could convert more of the surrounding code to the APM. And there's a lot of it to convert.

If I set the SyncContext property to null, am I still guaranteed to have only one thread executing inside the iterator at once? I'm assuming that if SyncContext is null, the callback can happen on any ThreadPool thread; I'm not sure if this means that multiple callbacks can now happen at once since they're not all necessarily being dispatched to the same thread (as far as I know).

Thanks,
Simon

--- In PowerThreading@yahoogroups.com, "Jeffrey Richter (Wintellect LLC)" <JeffreyR@...> wrote:
>
> Short answer: after new'ing up the ae, do this: ae.SyncConext = null;
>
> You can search the Yahoo news group for other posts about hanging and SyncContext.
> Alternatively, don't wait for the AE synchronously by calling EndExecute the way you. This kinda defeats the purpose of using the AE anyway.
>
> -- Jeffrey Richter (http://Wintellect.com<http://wintellect.com/>)
>
> From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of simonyun
> Sent: Wednesday, August 12, 2009 6:50 AM
> To: PowerThreading@yahoogroups.com
> Subject: [PowerThreading] AsyncEnumerator blocking forever when called sync from ASP.NET MVC 2 controller
>
>
>
> Hi everyone,
>
> I'm trying to use an AsyncEnumerator that's called (ultimately) from an ASP.NET MVC 2 controller:
>
> AsyncEnumerator<List<string>> ae = new AsyncEnumerator<List<string>>();
> List<string> list = ae.EndExecute(ae.BeginExecute(MyEnumerator(ae, "foo bar"), null));
>
> When I execute this code in a unit test or test console app, it runs fine (it's being called from the main thread). However, when I execute it in the web site, it blocks forever (it's being called from a worker thread). My enumerator just never gets called after the yield return 1; it looks like the calls to the AsyncCallbacks in my async operations within my enumerator are stuck in sleep/wait/join. I am sure that all the asynchronous operations I'm performing within my enumerator are returning properly.
>
> Do I need to do anything special to make this work? Thanks in advance.
>
> Simon
>


#590 From: "simonyun" <simonyun@...>
Date: Fri Aug 14, 2009 4:46 am
Subject: Re: FW: Timeouts
simonyun
Send Email Send Email
 
Thank you for the response.

Actually, in my case I *do* want a timeout on the first operation.  Then, after
that operation completes, I want to set a new timeout value for the parallel
operations.  Is there any way to avoid the race condition in this case without
using two separate AEs?

Simon

--- In PowerThreading@yahoogroups.com, "Jeffrey Richter (Wintellect LLC)"
<JeffreyR@...> wrote:
>
> If you want to execute the first operation without a timeout at all, then just
don't call SetCancelTimeout until after it competes before you initiate the
parallel operations.
> -- Jeffrey Richter (http://Wintellect.com<http://wintellect.com/>)
>
> From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com]
On Behalf Of simonyun
> Sent: Thursday, August 13, 2009 4:26 PM
> To: PowerThreading@yahoogroups.com
> Subject: [PowerThreading] Re: FW: Timeouts
>
>
>
> Jeffrey,
>
> Do you have a recommended way to guard against the race condition you describe
below? I want to use an async enumerator to first execute one async operation
with a timeout, followed by several operations in parallel with a different
timeout value.
>
> I'm worried about the race condition since it could prevent subsequent
operations from being processed properly because IsCanceled() will return true
as a result of the first timer's expiration before the second call to
SetCancelTimeout() can be made.
>
> Thanks,
> Simon
>
> --- In
PowerThreading@yahoogroups.com<mailto:PowerThreading%40yahoogroups.com>,
"Jeffrey Richter (Wintellect LLC)" <JeffreyR@<mailto:JeffreyR@>> wrote:
> >
> > Well, I got free minute and I looked at my code...Good news: I already do
what you want.
> > Yes, you can periodically call SetCancelTimeout. When you do, I dispose of
the current timer, and if you don't pass Timeout.Infinite (-1), then I create a
new Timer that goes off when you want it to.
> > Note, that there may be a race condition though: after a yield return, your
iterator code may be executing and the current timer could go off before you
call SetCancelTimeout.
> > If this happens, then the next time, you call yield return, I will call back
into your code immediately and IsCanceled will return true.
> >
> > -- Jeffrey Richter (http://Wintellect.com<http://wintellect.com/>)
> >
> > From:
PowerThreading@yahoogroups.com<mailto:PowerThreading%40yahoogroups.com>
[mailto:PowerThreading@yahoogroups.com<mailto:PowerThreading%40yahoogroups.com>]
On Behalf Of jon_reis
> > Sent: Tuesday, February 17, 2009 9:58 AM
> > To: PowerThreading@yahoogroups.com<mailto:PowerThreading%40yahoogroups.com>
> > Subject: [PowerThreading] Re: FW: Timeouts
> >
> >
> > Hi Jeffrey, thanks for taking the time to help me out.
> >
> > I tried your suggestion to implement my own EndExecute function to handle
exceptions thrown by Process and this works nicely. Thank you.
> >
> > I tried your suggestion of using the overloaded ae.End() that takes a dicard
group. I am using ae.End(0, c => null) everywhere since I don't need to do
anything special to clean up. Is this OK, or should I be doing something else?
> >
> > I tried your suggestion of using a DiscardGroup, but I'm still a little
confused as to how these function. The code as I have it below does not work
properly. It seems the DiscardGroup remembers that group 0, has been discarded
and causes the call to //(1) to be discarded during the second iteration of the
while loop. Am I supposed to increment the DiscardGroup each time I use it up to
a maximum of 64? Besides being pretty combersome, it will only allow me to
receive 64 messages before I run out of DiscardGroups. I don't understand the
usecase for DiscardGroup, what I really want is a DiscardPending that throws out
all pending operations. I'm sure like the other things I have run into that I
must be missing something here.
> >
> > In your original response you state:
> >
> > [JR] No. SetCancelTimeout applies to the entire AE object. That is, you are
cancelling the whole workflow, not just a part of it.
> >
> > I do want to cancel the entire workflow, but I want to change the timeout
for each operation. Like:
> >
> > ae.SetCancelTimeout(60000,null); // read for 60 seconds
> > stream.BeginRead(bbuffer.Array, bbuffer.Length, bbuffer.SpaceAvailable,
ae.End(0, c => null), null);
> > yeild 1;
> > ae.SetCancelTimeout(-1,null); // turn off cancel
> > if(ae.IsCanceled()) yield break;
> >
> > Will the second call to SetCancelTimout disable the timeout?
> >
> >
> >
> > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> > private void Start()
> > {
> > AsyncEnumerator ae = new AsyncEnumerator();
> > ae.BeginExecute(Process(ae, _listener), EndExecute, ae);
> > }
> >
> > private void EndExecute(IAsyncResult result)
> > {
> > try
> > {
> > AsyncEnumerator ae = (AsyncEnumerator)result.AsyncState;
> > ae.EndExecute(result);
> > }
> > catch(Exception ex)
> > {
> > if(OnException != null) OnException(this, ex);
> > }
> > }
> >
> > private IEnumerator<Int32> Process(AsyncEnumerator ae, TcpListener server)
> > {
> > server.BeginAcceptTcpClient(ae.End(0,c=>null), null);
> > yield return 1;
> >
> > if(_isExiting)
> > yield break;
> >
> > using(TcpClient client = server.EndAcceptTcpClient(ae.DequeueAsyncResult()))
> > {
> > int timeout = 60000;
> > Start(); // Accept another client
> > using(Stream stream = client.GetStream())
> > {
> > CountdownTimer countdownTimer = new CountdownTimer();
> > Buffer<byte> bbuffer = new Buffer<byte>();
> > while(true)
> > {
> > bbuffer.SpaceAvailable += 64 * 1024;
> > stream.BeginRead(bbuffer.Array, bbuffer.Length, bbuffer.SpaceAvailable,
ae.End(0, c => null), null); //(1)
> > countdownTimer.BeginCountdown(timeout, ae.End(0, c=>null), ae);
> > yield return 1;
> >
> > timeout = 5000;
> > if(countdownTimer.Expired) // I added this method to the timer you gave me
> > {
> > ae.DiscardGroup(0);
> > break;
> > }
> > int result = stream.EndRead(ae.DequeueAsyncResult());
> > ae.DiscardGroup(0);
> >
> > if(result == 0) break; //client shutdown
> > bbuffer.Length += result;
> > if(bbuffer.Array.ReverseFind(0, bbuffer.Length, _framing.EndFrameBytes) >=
0) // look for end of message marker
> > {
> > // Write outputData back to client
> > stream.BeginWrite(bbuffer.Array, 0, bbuffer.Length, ae.End(0, c => null),
null);
> > yield return 1;
> >
> > stream.EndWrite(ae.DequeueAsyncResult());
> > bbuffer.Length = 0;
> > timeout = 60000; // wait longer for the start of the next message
> > }
> > }
> > }
> > }
> > }
> >
>

#591 From: "Jeffrey Richter (Wintellect LLC)" <JeffreyR@...>
Date: Fri Aug 14, 2009 12:18 pm
Subject: Re: Re: FW: Timeouts
jeffrey.richter
Send Email Send Email
 
No, there is no way.

Sent from mobile device.


On Aug 13, 2009, at 9:46 PM, "simonyun" <simonyun@...> wrote:

 

Thank you for the response.

Actually, in my case I *do* want a timeout on the first operation. Then, after that operation completes, I want to set a new timeout value for the parallel operations. Is there any way to avoid the race condition in this case without using two separate AEs?

Simon

--- In PowerThreading@yahoogroups.com, "Jeffrey Richter (Wintellect LLC)" <JeffreyR@...> wrote:
>
> If you want to execute the first operation without a timeout at all, then just don't call SetCancelTimeout until after it competes before you initiate the parallel operations.
> -- Jeffrey Richter (http://Wintellect.com<http://wintellect.com/>)
>
> From: PowerThreading@yahoogroups.com [mailto:PowerThreading@yahoogroups.com] On Behalf Of simonyun
> Sent: Thursday, August 13, 2009 4:26 PM
> To: PowerThreading@yahoogroups.com
> Subject: [PowerThreading] Re: FW: Timeouts
>
>
>
> Jeffrey,
>
> Do you have a recommended way to guard against the race condition you describe below? I want to use an async enumerator to first execute one async operation with a timeout, followed by several operations in parallel with a different timeout value.
>
> I'm worried about the race condition since it could prevent subsequent operations from being processed properly because IsCanceled() will return true as a result of the first timer's expiration before the second call to SetCancelTimeout() can be made.
>
> Thanks,
> Simon
>
> --- In PowerThreading@yahoogroups.com<mailto:PowerThreading%40yahoogroups.com>, "Jeffrey Richter (Wintellect LLC)" <JeffreyR@<mailto:JeffreyR@>> wrote:
> >
> > Well, I got free minute and I looked at my code...Good news: I already do what you want.
> > Yes, you can periodically call SetCancelTimeout. When you do, I dispose of the current timer, and if you don't pass Timeout.Infinite (-1), then I create a new Timer that goes off when you want it to.
> > Note, that there may be a race condition though: after a yield return, your iterator code may be executing and the current timer could go off before you call SetCancelTimeout.
> > If this happens, then the next time, you call yield return, I will call back into your code immediately and IsCanceled will return true.
> >
> > -- Jeffrey Richter (http://Wintellect.com<http://wintellect.com/>)
> >
> > From: PowerThreading@yahoogroups.com<mailto:PowerThreading%40yahoogroups.com> [mailto:PowerThreading@yahoogroups.com<mailto:PowerThreading%40yahoogroups.com>] On Behalf Of jon_reis
> > Sent: Tuesday, February 17, 2009 9:58 AM
> > To: PowerThreading@yahoogroups.com<mailto:PowerThreading%40yahoogroups.com>
> > Subject: [PowerThreading] Re: FW: Timeouts
> >
> >
> > Hi Jeffrey, thanks for taking the time to help me out.
> >
> > I tried your suggestion to implement my own EndExecute function to handle exceptions thrown by Process and this works nicely. Thank you.
> >
> > I tried your suggestion of using the overloaded ae.End() that takes a dicard group. I am using ae.End(0, c => null) everywhere since I don't need to do anything special to clean up. Is this OK, or should I be doing something else?
> >
> > I tried your suggestion of using a DiscardGroup, but I'm still a little confused as to how these function. The code as I have it below does not work properly. It seems the DiscardGroup remembers that group 0, has been discarded and causes the call to //(1) to be discarded during the second iteration of the while loop. Am I supposed to increment the DiscardGroup each time I use it up to a maximum of 64? Besides being pretty combersome, it will only allow me to receive 64 messages before I run out of DiscardGroups. I don't understand the usecase for DiscardGroup, what I really want is a DiscardPending that throws out all pending operations. I'm sure like the other things I have run into that I must be missing something here.
> >
> > In your original response you state:
> >
> > [JR] No. SetCancelTimeout applies to the entire AE object. That is, you are cancelling the whole workflow, not just a part of it.
> >
> > I do want to cancel the entire workflow, but I want to change the timeout for each operation. Like:
> >
> > ae.SetCancelTimeout(60000,null); // read for 60 seconds
> > stream.BeginRead(bbuffer.Array, bbuffer.Length, bbuffer.SpaceAvailable, ae.End(0, c => null), null);
> > yeild 1;
> > ae.SetCancelTimeout(-1,null); // turn off cancel
> > if(ae.IsCanceled()) yield break;
> >
> > Will the second call to SetCancelTimout disable the timeout?
> >
> >
> >
> > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> > private void Start()
> > {
> > AsyncEnumerator ae = new AsyncEnumerator();
> > ae.BeginExecute(Process(ae, _listener), EndExecute, ae);
> > }
> >
> > private void EndExecute(IAsyncResult result)
> > {
> > try
> > {
> > AsyncEnumerator ae = (AsyncEnumerator)result.AsyncState;
> > ae.EndExecute(result);
> > }
> > catch(Exception ex)
> > {
> > if(OnException != null) OnException(this, ex);
> > }
> > }
> >
> > private IEnumerator<Int32> Process(AsyncEnumerator ae, TcpListener server)
> > {
> > server.BeginAcceptTcpClient(ae.End(0,c=>null), null);
> > yield return 1;
> >
> > if(_isExiting)
> > yield break;
> >
> > using(TcpClient client = server.EndAcceptTcpClient(ae.DequeueAsyncResult()))
> > {
> > int timeout = 60000;
> > Start(); // Accept another client
> > using(Stream stream = client.GetStream())
> > {
> > CountdownTimer countdownTimer = new CountdownTimer();
> > Buffer<byte> bbuffer = new Buffer<byte>();
> > while(true)
> > {
> > bbuffer.SpaceAvailable += 64 * 1024;
> > stream.BeginRead(bbuffer.Array, bbuffer.Length, bbuffer.SpaceAvailable, ae.End(0, c => null), null); //(1)
> > countdownTimer.BeginCountdown(timeout, ae.End(0, c=>null), ae);
> > yield return 1;
> >
> > timeout = 5000;
> > if(countdownTimer.Expired) // I added this method to the timer you gave me
> > {
> > ae.DiscardGroup(0);
> > break;
> > }
> > int result = stream.EndRead(ae.DequeueAsyncResult());
> > ae.DiscardGroup(0);
> >
> > if(result == 0) break; //client shutdown
> > bbuffer.Length += result;
> > if(bbuffer.Array.ReverseFind(0, bbuffer.Length, _framing.EndFrameBytes) >= 0) // look for end of message marker
> > {
> > // Write outputData back to client
> > stream.BeginWrite(bbuffer.Array, 0, bbuffer.Length, ae.End(0, c => null), null);
> > yield return 1;
> >
> > stream.EndWrite(ae.DequeueAsyncResult());
> > bbuffer.Length = 0;
> > timeout = 60000; // wait longer for the start of the next message
> > }
> > }
> > }
> > }
> > }
> >
>


Messages 561 - 591 of 1095   Oldest  |  < Older  |  Newer >  |  Newest
Add to My Yahoo!      XML What's This?

Copyright © 2010 Yahoo! Inc. All rights reserved.
Privacy Policy - Terms of Service - Guidelines NEW - Help