Skip to content

Instantly share code, notes, and snippets.

@noseratio
Last active May 2, 2023 11:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save noseratio/10685631 to your computer and use it in GitHub Desktop.
Save noseratio/10685631 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
namespace ProductsApp.Controllers
{
// http://stackoverflow.com/q/23062154/1768303
/// <summary>
/// CurrentThreadSyncContext
/// </summary>
class CurrentThreadSyncContext: SynchronizationContext, IDisposable
{
SynchronizationContext _existingCtx;
TaskScheduler _ts;
public CurrentThreadSyncContext(SynchronizationContext existingCtx = null)
{
_existingCtx = existingCtx?? SynchronizationContext.Current;
if (_existingCtx == null)
throw new InvalidProgramException("existingCtx");
_ts = new CurrentThreadTaskScheduler();
SynchronizationContext.SetSynchronizationContext(this);
}
public override void Post(SendOrPostCallback d, object state)
{
// make the _ts TaskScheduler.Current
var task = new Task(() =>
_existingCtx.Post(d, state));
task.RunSynchronously(_ts);
}
public override void Send(SendOrPostCallback d, object state)
{
_existingCtx.Send(d, state);
}
public override SynchronizationContext CreateCopy()
{
return new CurrentThreadSyncContext(_existingCtx.CreateCopy());
}
public void Dispose()
{
if (_existingCtx != null && SynchronizationContext.Current == this)
SynchronizationContext.SetSynchronizationContext(_existingCtx);
}
/// <summary>
/// CurrentThreadTaskScheduler
/// http://blogs.msdn.com/b/pfxteam/archive/2010/04/09/9990424.aspx
/// </summary>
class CurrentThreadTaskScheduler : TaskScheduler
{
protected override void QueueTask(Task task)
{
TryExecuteTask(task);
}
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
return TryExecuteTask(task);
}
protected override IEnumerable<Task> GetScheduledTasks()
{
return Enumerable.Empty<Task>();
}
public override int MaximumConcurrencyLevel { get { return 1; } }
}
}
/// <summary>
/// TestController
/// </summary>
public class TestController : ApiController
{
public async Task<string> GetData()
{
using (var ctx = new CurrentThreadSyncContext())
{
Debug.WriteLine(new
{
where = "1) before await",
thread = Thread.CurrentThread.ManagedThreadId,
context = SynchronizationContext.Current
});
await Task.Delay(100).ContinueWith(t =>
{
Debug.WriteLine(new
{
where = "2) inside ContinueWith",
thread = Thread.CurrentThread.ManagedThreadId,
context = SynchronizationContext.Current
});
}, TaskContinuationOptions.ExecuteSynchronously); //.ConfigureAwait(false);
Debug.WriteLine(new
{
where = "3) after await",
thread = Thread.CurrentThread.ManagedThreadId,
context = SynchronizationContext.Current
});
}
return "OK";
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment