Skip to content

Instantly share code, notes, and snippets.

@NikiforovAll
Last active December 18, 2020 23:52
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 NikiforovAll/aaefc21d2c979222c1c4fe7f9b3f4943 to your computer and use it in GitHub Desktop.
Save NikiforovAll/aaefc21d2c979222c1c4fe7f9b3f4943 to your computer and use it in GitHub Desktop.
playing with continuewith and custom synchronization context

Run

git clone https://gist.github.com/aaefc21d2c979222c1c4fe7f9b3f4943.git continue-with-and-custom-scheduler
cd continue-with-and-custom-scheduler
dotnet run
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace cancellation_demo1
{
public static class ContinueWith
{
internal static void Run()
{
// var scheduler = new ConcurrentExclusiveSchedulerPair().ExclusiveScheduler;
// var scheduler = TaskScheduler.Current;
var scheduler = new SchedulerContainer.SynchronizationContextTaskScheduler(new SynchronizationContext());
foreach (var _ in new int[]{1,2,3,4,5})
{
new TaskFactory(scheduler).StartNew(RunInternal).ConfigureAwait(true);
}
Console.ReadKey();
}
internal static void RunInternal()
{
// SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
var scheduler = new ConcurrentExclusiveSchedulerPair().ExclusiveScheduler;
// TaskScheduler.UnobservedTaskException
// SynchronizationContext.SetSynchronizationContext(null);
Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId + $"|{Thread.CurrentThread.Name} - {Thread.CurrentThread.ThreadState}");
var t = Task.Factory.StartNew(() =>
{
Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId + $"|{Thread.CurrentThread.Name} - {Thread.CurrentThread.ThreadState}");
}, default, TaskCreationOptions.None, TaskScheduler.Current)
.ContinueWith(
_ =>
Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId + $"|{Thread.CurrentThread.Name} - {Thread.CurrentThread.ThreadState}"),
TaskScheduler.Current
);
t.Wait();
}
}
public static class SchedulerContainer
{
public class SynchronizationContextTaskScheduler : TaskScheduler
{
private ConcurrentQueue<Task> _tasks = new();
private SynchronizationContext _context;
public SynchronizationContextTaskScheduler() :
this(SynchronizationContext.Current)
{ }
public SynchronizationContextTaskScheduler(
SynchronizationContext context)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
}
protected override void QueueTask(Task task)
{
// Add the task to the collection
_tasks.Enqueue(task);
// Queue up a delegate that will dequeue and execute a task
_context.Post(delegate
{
Task toExecute;
if (_tasks.TryDequeue(out toExecute)) TryExecuteTask(toExecute);
}, null);
}
protected override bool TryExecuteTaskInline(
Task task, bool taskWasPreviouslyQueued)
{
return SynchronizationContext.Current == _context &&
TryExecuteTask(task);
}
public override int MaximumConcurrencyLevel { get { return 1; } }
protected override IEnumerable<Task> GetScheduledTasks()
{
return _tasks.ToArray();
}
}
}
}
using System.Threading;
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
namespace cancellation_demo1
{
class Program
{
static CancellationTokenSource cts = new();
static async Task Main(string[] args)
{
ContinueWith.Run();
// var task1 = Do3();
// Task result = Task.WhenAny(Do2(), Do1(), Do3());
// await result;
// System.Console.WriteLine($"Finished... {result.Status}/task1{task1.Status}");
}
private static async Task Do2()
{
await Task.Delay(TimeSpan.FromSeconds(2), cts.Token);
System.Console.WriteLine("Processed Do2");
}
private static async Task Do1()
{
await Task.Delay(100);
cts.Cancel();
}
private static async Task Do3()
{
await Task.Delay(0);
throw new Exception(nameof(Do3));
}
}
}
set -e
desc="playing with continuewith and custom synchronization context"
DEMO_NAME=`basename $PWD`
GIST_ID=$(gh gist create --public --desc "$desc" "$@" | grep https)
echo $GIST_ID
gh gist edit $GIST_ID -f README.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment