public void MultipleDeserializeCallsShouldNotContend() { var data = new ThreadRace.Y9(); byte[] raw; using (var ms = new MemoryStream()) { RuntimeTypeModel.Create().Serialize(ms, data); raw = ms.ToArray(); Assert.True(raw.Length > 0); } const int threads = 10, loop = 500; for (int loopIndex = 0; loopIndex < loop; loopIndex++) { int building = threads, error = 0; Thread[] threadArr = new Thread[threads]; ManualResetEvent evt = new ManualResetEvent(false); var model = RuntimeTypeModel.Create(); string eek = null; int eekCount = 0; model.LockContended += (s, a) => { eek = a.OwnerStackTrace; Interlocked.Increment(ref eekCount); }; for (int i = 0; i < threads; i++) { threadArr[i] = new Thread(() => { try { using var ms = new MemoryStream(raw); if (Interlocked.Decrement(ref building) == 0) { evt.Set(); } else { evt.WaitOne(); } #pragma warning disable CS0618 ThreadRace.A a = (ThreadRace.A)model.Deserialize(ms, null, typeof(ThreadRace.A)); #pragma warning restore CS0618 Assert.IsType <ThreadRace.Y9>(a); } catch { Interlocked.Increment(ref error); } }); } foreach (var thd in threadArr) { thd.Start(); } foreach (var thd in threadArr) { if (!thd.Join(4000)) { throw new TimeoutException(); } } Assert.Equal(0, Interlocked.CompareExchange(ref error, 0, 0)); Assert.Null(eek); Assert.Equal(0, Interlocked.CompareExchange(ref eekCount, 0, 0)); } }
public void MultipleDeserializeCallsShouldNotContend() { var data = new ThreadRace.Y9(); byte[] raw; using (var ms = new MemoryStream()) { RuntimeTypeModel.Create().Serialize(ms, data); raw = ms.ToArray(); Assert.That(raw.Length, Is.GreaterThan(0)); } #if DEBUG const int threads = 5; const int loop = 5; #else const int threads = 10; const int loop = 500; #endif for (int loopIndex = 0; loopIndex < loop; loopIndex++) { int building = threads, error = 0; Thread[] threadArr = new Thread[threads]; ManualResetEvent evt = new ManualResetEvent(false); var model = RuntimeTypeModel.Create(); model.SkipCompiledVsNotCheck = true; string eek = null; int eekCount = 0; model.LockContended += (s, a) => { eek = a.OwnerStackTrace; Interlocked.Increment(ref eekCount); }; for (int i = 0; i < threads; i++) { threadArr[i] = new Thread(() => { try { using (var ms = new MemoryStream(raw)) { if (Interlocked.Decrement(ref building) == 0) { evt.Set(); } else { evt.WaitOne(); } ThreadRace.A a = (ThreadRace.A)model.Deserialize(ms, null, typeof(ThreadRace.A)); Assert.That(a, Is.InstanceOfType(typeof(ThreadRace.Y9))); } } catch { Interlocked.Increment(ref error); } }); } foreach (var thd in threadArr) { thd.Start(); } foreach (var thd in threadArr) { if (!thd.Join(4000)) { throw new TimeoutException(); } } Assert.That(Interlocked.CompareExchange(ref error, 0, 0), Is.EqualTo(0)); Assert.That(eek, Is.Null); Assert.That(Interlocked.CompareExchange(ref eekCount, 0, 0), Is.EqualTo(0)); } }