// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#if NET_4_0 || MOBILE
+#if NET_4_0
using System.Collections.Generic;
using System.Collections.Concurrent;
canceled = true;
handle.Set ();
+ if (linkedTokens != null)
+ UnregisterLinkedTokens ();
List<Exception> exceptions = null;
throw new AggregateException (exceptions);
}
+ /* This is the callback registered on linked tokens
+ * so that they don't throw an ODE if the callback
+ * is called concurrently with a Dispose
+ */
+ void SafeLinkedCancel ()
+ {
+ try {
+ Cancel ();
+ } catch (ObjectDisposedException) {}
+ }
+
#if NET_4_5
public void CancelAfter (TimeSpan delay)
{
throw new ArgumentException ("Empty tokens array");
CancellationTokenSource src = new CancellationTokenSource ();
- Action action = src.Cancel;
+ Action action = src.SafeLinkedCancel;
var registrations = new List<CancellationTokenRegistration> (tokens.Length);
foreach (CancellationToken token in tokens) {
void UnregisterLinkedTokens ()
{
- if (linkedTokens == null)
+ var registrations = Interlocked.Exchange (ref linkedTokens, null);
+ if (registrations == null)
return;
- foreach (var linked in linkedTokens)
+ foreach (var linked in registrations)
linked.Dispose ();
- linkedTokens = null;
}
internal CancellationTokenRegistration Register (Action callback, bool useSynchronizationContext)