// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_4_5
using System;
using System.Threading;
using System.Runtime.CompilerServices;
using System.Collections.Generic;
using System.Collections;
+using System.Collections.Concurrent;
namespace MonoTests.System.Runtime.CompilerServices
{
}
}
+ class NestedSynchronizationContext : SynchronizationContext
+ {
+ Thread thread;
+ readonly ConcurrentQueue<Tuple<SendOrPostCallback, object, ExecutionContext>> workQueue = new ConcurrentQueue<Tuple<SendOrPostCallback, object, ExecutionContext>> ();
+ readonly AutoResetEvent workReady = new AutoResetEvent (false);
+
+ public NestedSynchronizationContext ()
+ {
+ thread = new Thread (WorkerThreadProc) { IsBackground = true };
+ thread.Start ();
+ }
+
+ public override void Post (SendOrPostCallback d, object state)
+ {
+ var context = ExecutionContext.Capture ();
+ workQueue.Enqueue (Tuple.Create (d, state, context));
+ workReady.Set ();
+ }
+
+ void WorkerThreadProc ()
+ {
+ if (!workReady.WaitOne (10000))
+ return;
+
+ Tuple<SendOrPostCallback, object, ExecutionContext> work;
+
+ while (workQueue.TryDequeue (out work)) {
+ ExecutionContext.Run (work.Item3, _ => {
+ var oldSyncContext = SynchronizationContext.Current;
+ SynchronizationContext.SetSynchronizationContext (this);
+ work.Item1 (_);
+ SynchronizationContext.SetSynchronizationContext (oldSyncContext);
+ }, work.Item2);
+ }
+ }
+ }
+
string progress;
SynchronizationContext sc;
ManualResetEvent mre;
}
[Test]
+ [Ignore ("Incompatible with nunitlite")]
public void FinishedTaskOnCompleted ()
{
var mres = new ManualResetEvent (false);
mres.Set ();
// this will only terminate correctly if the test was not executed from the main thread
- // e.g. Touch.Unit defaults to run tests on the main thread and this will return false
+ // e.g. nunitlite/Touch.Unit defaults to run tests on the main thread and this will return false
Assert.AreEqual (Thread.CurrentThread.IsBackground, mres2.WaitOne (2000), "#2");;
}
SynchronizationContext.SetSynchronizationContext (null);
}
+
+ [Test]
+ public void NestedLeakingSynchronizationContext ()
+ {
+ var sc = SynchronizationContext.Current;
+ if (sc == null)
+ Assert.IsTrue (NestedLeakingSynchronizationContext_MainAsync (sc).Wait (5000), "#1");
+ else
+ Assert.Ignore ("NestedSynchronizationContext may never complete on custom context");
+ }
+
+ static async Task NestedLeakingSynchronizationContext_MainAsync (SynchronizationContext sc)
+ {
+ Assert.AreSame (sc, SynchronizationContext.Current, "#1");
+ await NestedLeakingSynchronizationContext_DoWorkAsync ();
+ Assert.AreSame (sc, SynchronizationContext.Current, "#2");
+ }
+
+ static async Task NestedLeakingSynchronizationContext_DoWorkAsync ()
+ {
+ var sc = new NestedSynchronizationContext ();
+ SynchronizationContext.SetSynchronizationContext (sc);
+
+ Assert.AreSame (sc, SynchronizationContext.Current);
+ await Task.Yield ();
+ Assert.AreSame (sc, SynchronizationContext.Current);
+ }
}
}
-#endif