Skip to content

Instantly share code, notes, and snippets.

@gamlerhart
Created November 8, 2010 20:49

Revisions

  1. gamlerhart revised this gist Nov 8, 2010. 1 changed file with 2 additions and 7 deletions.
    9 changes: 2 additions & 7 deletions MyPrimitiveSynchronisationContext.cs
    Original file line number Diff line number Diff line change
    @@ -36,7 +36,7 @@ public void RunOneRound()
    nextToRun();
    }

    public void Cancel()
    public void Dispose()
    {
    lock (syncHandle)
    {
    @@ -45,11 +45,6 @@ public void Cancel()
    }
    }

    public void Dispose()
    {
    Cancel();
    }

    private Action GrabItem()
    {
    lock (syncHandle)
    @@ -74,4 +69,4 @@ private void SignalContinue()
    {
    Monitor.Pulse(syncHandle);
    }
    }
    }
  2. gamlerhart revised this gist Nov 8, 2010. 3 changed files with 129 additions and 0 deletions.
    12 changes: 12 additions & 0 deletions ComplexBusinessOperationsTest-3.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,12 @@
    [Test]
    public void EarnMoney()
    {
    TestSyncContext.Run(
    awaiter=>
    {
    var toTest = new ComplexBusinessOperations();
    var task = toTest.EarnMoneyAsync(200);
    awaiter.WaitFor(task);
    Assert.AreEqual(400, toTest.MoneyEarnedSoFar);
    });
    }
    77 changes: 77 additions & 0 deletions MyPrimitiveSynchronisationContext.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,77 @@
    class MyPrimitiveSynchronisationContext : SynchronizationContext, IDisposable
    {
    private readonly Queue<Action> messagesToProcess = new Queue<Action>();
    private readonly object syncHandle = new object();
    private bool isRunning = true;

    public override void Send(SendOrPostCallback codeToRun, object state)
    {
    throw new NotImplementedException();
    }

    public override void Post(SendOrPostCallback codeToRun, object state)
    {
    lock (syncHandle)
    {
    if(!isRunning)
    {
    throw new InvalidOperationException("Cannot post messages to a closes message pump");
    }
    messagesToProcess.Enqueue(() => codeToRun(state));
    SignalContinue();
    }
    }

    public void RunMessagePump()
    {
    while (CanContinue())
    {
    RunOneRound();
    }
    }

    public void RunOneRound()
    {
    Action nextToRun = GrabItem();
    nextToRun();
    }

    public void Cancel()
    {
    lock (syncHandle)
    {
    isRunning = false;
    SignalContinue();
    }
    }

    public void Dispose()
    {
    Cancel();
    }

    private Action GrabItem()
    {
    lock (syncHandle)
    {
    while (CanContinue() && messagesToProcess.Count == 0)
    {
    Monitor.Wait(syncHandle);
    }
    return messagesToProcess.Dequeue();
    }
    }

    private bool CanContinue()
    {
    lock (syncHandle)
    {
    return isRunning;
    }
    }

    private void SignalContinue()
    {
    Monitor.Pulse(syncHandle);
    }
    }
    40 changes: 40 additions & 0 deletions TestSyncContext.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,40 @@
    public static class TestSyncContext
    {
    public static void Run(Action<Awaiter> testToRun)
    {
    using(var msgPump = new MyPrimitiveSynchronisationContext())
    {
    var syncContextBackup = SynchronizationContext.Current;
    try
    {
    SynchronizationContext.SetSynchronizationContext(msgPump);
    var awaiter = new Awaiter(msgPump);
    msgPump.Post(obj => testToRun(awaiter), null);
    msgPump.RunOneRound();
    }
    finally
    {
    SynchronizationContext.SetSynchronizationContext(syncContextBackup);
    }
    }
    }

    }

    public class Awaiter
    {
    private readonly MyPrimitiveSynchronisationContext syncContext;

    internal Awaiter(MyPrimitiveSynchronisationContext syncContext)
    {
    this.syncContext = syncContext;
    }

    public void WaitFor(IAsyncResult toWaitOn)
    {
    while(!toWaitOn.IsCompleted)
    {
    syncContext.RunOneRound();
    }
    }
    }
  3. gamlerhart revised this gist Nov 8, 2010. 2 changed files with 8 additions and 8 deletions.
    14 changes: 7 additions & 7 deletions ComplexBusinessOperations-2.cs
    Original file line number Diff line number Diff line change
    @@ -7,23 +7,23 @@ public int MoneyEarnedSoFar
    get { return moneyEarnedSoFar; }
    }

    public async Task EarnMoney(int investment)
    public async Task EarnMoneyAsync(int investment)
    {
    var firstMoneyEarner = EarnMoneySubTaks(investment);
    var secondMoneyEarner = EarnMoneySubTaks(investment);
    var firstMoneyEarner = EarnMoneySubTaskAsync(investment);
    var secondMoneyEarner = EarnMoneySubTaskAsync(investment);
    await TaskEx.WhenAll(firstMoneyEarner, secondMoneyEarner);
    }

    private async Task EarnMoneySubTaks(int investment)
    private async Task EarnMoneySubTaskAsync(int investment)
    {
    for (int i = 0; i < investment; i++)
    {
    var result = await EarnOneDollar();
    var result = await EarnOneDollarAsync();
    moneyEarnedSoFar += result;
    }
    }

    private Task<int> EarnOneDollar()
    private Task<int> EarnOneDollarAsync()
    {
    return TaskEx.Run(
    () =>
    @@ -33,4 +33,4 @@ private Task<int> EarnOneDollar()
    return 1;
    });
    }
    }
    }
    2 changes: 1 addition & 1 deletion ComplexBusinessOperationsTest-2.cs
    Original file line number Diff line number Diff line change
    @@ -2,7 +2,7 @@
    public void EarnMoney()
    {
    var toTest = new ComplexBusinessOperations();
    var task = toTest.EarnMoney(200);
    var task = toTest.EarnMoneyAsync(200);
    task.Wait();
    Assert.AreEqual(400, toTest.MoneyEarnedSoFar);
    }
  4. gamlerhart revised this gist Nov 8, 2010. 4 changed files with 47 additions and 2 deletions.
    1 change: 1 addition & 0 deletions ComplexBusinessOperations-1.cs
    Original file line number Diff line number Diff line change
    @@ -24,6 +24,7 @@ private void EarnMoneySubTaks(int investment)

    private int EarnOneDollar()
    {
    // This operation takes a while
    Thread.Sleep(50);
    return 1;
    }
    36 changes: 36 additions & 0 deletions ComplexBusinessOperations-2.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,36 @@
    public class ComplexBusinessOperations
    {
    private int moneyEarnedSoFar;

    public int MoneyEarnedSoFar
    {
    get { return moneyEarnedSoFar; }
    }

    public async Task EarnMoney(int investment)
    {
    var firstMoneyEarner = EarnMoneySubTaks(investment);
    var secondMoneyEarner = EarnMoneySubTaks(investment);
    await TaskEx.WhenAll(firstMoneyEarner, secondMoneyEarner);
    }

    private async Task EarnMoneySubTaks(int investment)
    {
    for (int i = 0; i < investment; i++)
    {
    var result = await EarnOneDollar();
    moneyEarnedSoFar += result;
    }
    }

    private Task<int> EarnOneDollar()
    {
    return TaskEx.Run(
    () =>
    {
    // This operation takes a while
    Thread.Sleep(50);
    return 1;
    });
    }
    }
    4 changes: 2 additions & 2 deletions ComplexBusinessOperationsTest-1.cs
    Original file line number Diff line number Diff line change
    @@ -2,6 +2,6 @@
    public void EarnMoney()
    {
    var toTest = new ComplexBusinessOperations();
    toTest.EarnMoney(100);
    Assert.AreEqual(200, toTest.MoneyEarnedSoFar);
    toTest.EarnMoney(200);
    Assert.AreEqual(400, toTest.MoneyEarnedSoFar);
    }
    8 changes: 8 additions & 0 deletions ComplexBusinessOperationsTest-2.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,8 @@
    [Test]
    public void EarnMoney()
    {
    var toTest = new ComplexBusinessOperations();
    var task = toTest.EarnMoney(200);
    task.Wait();
    Assert.AreEqual(400, toTest.MoneyEarnedSoFar);
    }
  5. gamlerhart created this gist Nov 8, 2010.
    30 changes: 30 additions & 0 deletions ComplexBusinessOperations-1.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,30 @@
    public class ComplexBusinessOperations
    {
    private int moneyEarnedSoFar;

    public int MoneyEarnedSoFar
    {
    get { return moneyEarnedSoFar; }
    }

    public void EarnMoney(int investment)
    {
    EarnMoneySubTaks(investment);
    EarnMoneySubTaks(investment);
    }

    private void EarnMoneySubTaks(int investment)
    {
    for (int i = 0; i < investment; i++)
    {
    var result = EarnOneDollar();
    moneyEarnedSoFar += result;
    }
    }

    private int EarnOneDollar()
    {
    Thread.Sleep(50);
    return 1;
    }
    }
    7 changes: 7 additions & 0 deletions ComplexBusinessOperationsTest-1.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,7 @@
    [Test]
    public void EarnMoney()
    {
    var toTest = new ComplexBusinessOperations();
    toTest.EarnMoney(100);
    Assert.AreEqual(200, toTest.MoneyEarnedSoFar);
    }