From 14b42141c031514e1a8e93265cd0364e75a1c6f2 Mon Sep 17 00:00:00 2001 From: David Straw Date: Mon, 17 Sep 2012 11:17:03 -0600 Subject: [PATCH] Handle multiple concurrent calls to BeginTryReceiveRequest --- .../HttpReplyChannel.cs | 4 +-- .../ReplyChannelBase.cs | 29 ++++++++++--------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels.Http/HttpReplyChannel.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels.Http/HttpReplyChannel.cs index 5bc1c4dc3b3..378a200ff21 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels.Http/HttpReplyChannel.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels.Http/HttpReplyChannel.cs @@ -92,8 +92,8 @@ namespace System.ServiceModel.Channels.Http AbortConnections (timeout); // FIXME: this wait is sort of hack (because it should not be required), but without it some tests are blocked. // This hack even had better be moved to base.CancelAsync(). - if (CurrentAsyncResult != null) - CurrentAsyncResult.AsyncWaitHandle.WaitOne (TimeSpan.FromMilliseconds (300)); +// if (CurrentAsyncResult != null) +// CurrentAsyncResult.AsyncWaitHandle.WaitOne (TimeSpan.FromMilliseconds (300)); return base.CancelAsync (timeout); } diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/ReplyChannelBase.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/ReplyChannelBase.cs index 01d85a20b5d..9a66a324500 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/ReplyChannelBase.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/ReplyChannelBase.cs @@ -85,15 +85,16 @@ namespace System.ServiceModel.Channels protected override void OnClose (TimeSpan timeout) { - if (CurrentAsyncThread != null) + if (currentAsyncThreads.Count > 0) if (!CancelAsync (timeout)) - CurrentAsyncThread.Abort (); + foreach (Thread asyncThread in currentAsyncThreads) + asyncThread.Abort (); } public virtual bool CancelAsync (TimeSpan timeout) { // FIXME: It should wait for the actual completion. - return CurrentAsyncResult == null; + return currentAsyncResults.Count > 0; //return CurrentAsyncResult == null || CurrentAsyncResult.AsyncWaitHandle.WaitOne (timeout); } @@ -109,34 +110,34 @@ namespace System.ServiceModel.Channels TryReceiveDelegate try_recv_delegate; object async_result_lock = new object (); - protected Thread CurrentAsyncThread { get; private set; } - protected IAsyncResult CurrentAsyncResult { get; private set; } + HashSet currentAsyncThreads = new HashSet(); + HashSet currentAsyncResults = new HashSet(); public virtual IAsyncResult BeginTryReceiveRequest (TimeSpan timeout, AsyncCallback callback, object state) { - if (CurrentAsyncResult != null) - throw new InvalidOperationException ("Another async TryReceiveRequest operation is in progress"); + IAsyncResult result = null; + if (try_recv_delegate == null) try_recv_delegate = new TryReceiveDelegate (delegate (TimeSpan tout, out RequestContext ctx) { lock (async_result_lock) { - if (CurrentAsyncResult != null) - CurrentAsyncThread = Thread.CurrentThread; + if (currentAsyncResults.Contains (result)) + currentAsyncThreads.Add (Thread.CurrentThread); } try { return TryReceiveRequest (tout, out ctx); } finally { lock (async_result_lock) { - CurrentAsyncResult = null; - CurrentAsyncThread = null; + currentAsyncResults.Remove (result); + currentAsyncThreads.Remove (Thread.CurrentThread); } } }); RequestContext dummy; - IAsyncResult result; lock (async_result_lock) { - result = CurrentAsyncResult = try_recv_delegate.BeginInvoke (timeout, out dummy, callback, state); + result = try_recv_delegate.BeginInvoke (timeout, out dummy, callback, state); + currentAsyncResults.Add (result); } - // Note that at this point CurrentAsyncResult can be null here if delegate has run to completion + // Note that at this point result can be missing from currentAsyncResults here if delegate has run to completion return result; } -- 2.25.1