Skip to content

Instantly share code, notes, and snippets.

@binki

binki/Program.cs Secret

Created November 10, 2016 16:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save binki/7bf565bb398c419958f64ebddb14634b to your computer and use it in GitHub Desktop.
Save binki/7bf565bb398c419958f64ebddb14634b to your computer and use it in GitHub Desktop.
Example of running all the operations concurrently
Starting SynchronizationContext
0: Started
2: Started
2: Received number 1
2: Received number 2
2: Received number 3
2: Received number 4
2: Stopped
0: Received number 1
0: Received number 2
0: Received number 3
0: Received number 4
0: Stopped
1: Started
1: Received number 1
1: Received number 2
1: Received number 3
3: Started
1: Received number 4
1: Stopped
3: Received number 1
3: Received number 2
3: Received number 3
3: Received number 4
3: Stopped
SynchronizationContext finished
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting SynchronizationContext");
Nito.AsyncEx.AsyncContext.Run(Run);
Console.WriteLine("SynchronizationContext finished");
}
// This method is run like it is a UI callback. I.e., it has a
// single-threaded event-loop-based synchronization context which
// processes asynchronous callbacks.
static Task Run()
{
foreach (var i in Enumerable.Range(0, 4))
{
var demoOperation = new AsyncDemoUsingAsyncOperations();
demoOperation.Started += (sender, e) => Console.WriteLine($"{i}: Started");
demoOperation.NewNumber += (sender, e) => Console.WriteLine($"{i}: Received number {e.Num}");
demoOperation.Stopped += (sender, e) =>
{
// The AsyncDemoUsingAsyncOperation has a bug where it fails to call
// AsyncOperation.OperationCompleted(). Do that for it. If we don’t,
// the AsyncContext will never exit because there are outstanding unfinished
// asynchronous operations.
((AsyncOperation)typeof(AsyncDemoUsingAsyncOperations).GetField("asyncOp", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(demoOperation)).OperationCompleted();
Console.WriteLine($"{i}: Stopped");
};
demoOperation.Start();
}
// AsyncContext requires us to return a Task because that is its
// normal use case.
return Nito.AsyncEx.TaskConstants.Completed;
}
}
class AsyncDemoUsingAsyncOperations
{
AsyncOperation asyncOp;
bool isBusy;
void NotifyStarted()
{
isBusy = true;
Started(this, new EventArgs());
}
void NotifyStopped()
{
isBusy = false;
Stopped(this, new EventArgs());
}
public void Start()
{
if (isBusy)
throw new InvalidOperationException("Already working you moron...");
asyncOp = AsyncOperationManager.CreateOperation(null);
ThreadPool.QueueUserWorkItem(new WaitCallback(StartOperation));
}
public event EventHandler Started = delegate { };
public event EventHandler Stopped = delegate { };
public event EventHandler<NewNumberEventArgs> NewNumber = delegate { };
private void StartOperation(object state)
{
asyncOp.Post(args => NotifyStarted(), null);
for (int i = 1; i < 5; i++)
asyncOp.Post(args => NewNumber(this, args as NewNumberEventArgs), new NewNumberEventArgs(i));
asyncOp.Post(args => NotifyStopped(), null);
}
}
class NewNumberEventArgs : EventArgs
{
public int Num { get; private set; }
public NewNumberEventArgs(int num)
{
Num = num;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment