据我所知,AspNetCore没有 SynchronizationContext.
“重新进入”请求上下文涉及许多内务任务,例如设置 HttpContext.Current 和当前线程的身份和文化。
所以我创建了一个简单的 .Net Core Api 项目,并执行以下操作:
[HttpGet]
[Route("checkVar")]
public async Task<IActionResult> checkVar()
{
Thread.SetData(Thread.GetNamedDataSlot("Random"),4);
await Task.Delay(1000);
var res = Thread.GetData(Thread.GetNamedDataSlot("Random"));
}
Run Code Online (Sandbox Code Playgroud)
令我惊讶的是,res它的价值为4. 我很惊讶,因为我相信这SetData是同步上下文的一部分。(在asp.net core中不应该存在)
更多,当我使用时ConfigureAwait(false),我进入null了res。
所以现在我很困惑。因为ConfigureAwait 在asp.net core中不应该有影响
题:
如果 asp.net core 没有 SynchronizationContext,那么为什么在4之后可用await?为什么会ConfigureAwait在非 SynchronizationContext 环境中改变结果?
在使用ConfigureAwait(false)的引用库中使用Thread.CurrentPrincipal的声明会造成任何问题,或者ExecutionContext的逻辑调用上下文的流动会在那里照顾我吗?(到目前为止,我的阅读和测试表明它会).
示例WebAPI控制器操作:
[CustomAuthorizeThatSetsCurrentUsersClaimsToThreadCurrentContextAndHttpContextCurrentUser]
public async Task<Order> Get(int orderId)
{
return await _orderBusinessLogicLibrary.LoadAsync(orderId); // defaults to .ConfigureAwait(true)
}
Run Code Online (Sandbox Code Playgroud)
来自外部引用库的示例加载函数:
[ClaimsPrincipalPermission(
SecurityAction.Demand,
Operation="Read",
Resource="Orders")]
[ClaimsPrincipalPermission(
SecurityAction.Demand,
Operation="Read",
Resource="OrderItems")]
public async Task<Order> Load(int orderId)
{
var order = await _repository.LoadOrderAsync(orderId).ConfigureAwait(false);
// here's the key line.. assuming this lower-level function is also imposing
// security constraints in the same way this method does, would
// Thread.CurrentPrincipal still be correct inside the function below?
order.Items = await _repository.LoadOrderItemsAsync(orderId).ConfigureAwait(false);
return order;
}
Run Code Online (Sandbox Code Playgroud)
此外,答案不能是"那么不要使用ConfigureAwait(false)!".这可能会导致其他问题,例如死锁(请勿在异步代码上阻止).
claims-based-identity synchronizationcontext async-await current-principal executioncontext
我手动构建一个任务:
var task = new Task(() =>
Debug.WriteLine("Task"));
Run Code Online (Sandbox Code Playgroud)
然后手动启动它:
task.Start(TaskScheduler.FromCurrentSynchronizationContext());
Run Code Online (Sandbox Code Playgroud)
我希望它能通过预定SynchronizationContext.Post.
但如果以这种方式启动它:
task.RunSynchronously(TaskScheduler.FromCurrentSynchronizationContext());
Run Code Online (Sandbox Code Playgroud)
是通过SynchronizationContext.Send调用任务的lambda 来执行还是直接执行?
据我所知,Windows服务应用程序中没有同步上下文.
await fooTask.ConfigureAwait(false)给我的Windows服务中的任何好处? c# windows-services synchronizationcontext task-parallel-library async-await
我正在阅读SynchronizationContext并尝试确保OperationContext即使在await通话之后我试图将所有线程都流入所有线程也不会弄乱任何东西.
我有这SynchronizationContext门课:
public class OperationContextSynchronizationContext : SynchronizationContext
{
// Track the context to make sure that it flows through to the next thread.
private readonly OperationContext _context;
public OperationContextSynchronizationContext(OperationContext context)
{
_context = context;
}
public override void Post(SendOrPostCallback d, object state)
{
OperationContext.Current = _context;
d(state);
}
}
Run Code Online (Sandbox Code Playgroud)
然后围绕每个方法调用(使用a Ninject IInterceptor)调用它:
var original = SynchronizationContext.Current;
try
{
// Make sure that the OperationContext flows across to the other threads,
// …Run Code Online (Sandbox Code Playgroud) 我有一个WPF应用程序,它使用System.Threading.Tasks在后台调用WCF服务.我正在使用Task.ContinueWith将服务调用的结果返回给WPF UI线程.我的问题是,虽然继续运行确实在UI线程上运行,但是它确实是SynchronizationContext.Current为null.我可以运行相同的代码,在初始Task中注释掉WCF调用,并且继续在UI线程上,并按预期使用DispatcherSynchronizationContext.
WCF代理使用ChannelFactory生成,并使用wsHttpBinding.没有回调合约.相关代码如下所示:
private TaskScheduler _uiScheduler;
public MainWindow()
{
InitializeComponent();
_uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var serviceTask = new Task<Int32>(ServiceCallWrapper,
CancellationToken.None,
TaskCreationOptions.None);
var continueTask = serviceTask.ContinueWith(result => ServiceContinuation(result.Result),
CancellationToken.None,
TaskContinuationOptions.OnlyOnRanToCompletion,
_uiScheduler);
serviceTask.Start();
}
private Int32 ServiceCallWrapper()
{
Int32 result = 0;
var service = {elided - initializes service using ChannelFactory };
result = service.TheServiceMethod();
service.Close();
return result;
}
private void ServiceContinuation(Int32 result)
{ elided }
Run Code Online (Sandbox Code Playgroud)
如果我按原样运行此代码,则在正确的线程上调用ServiceContinuation(使用ManagedThreadID验证),但SynchronizationContext.Current为null.如果我注释掉进行服务调用的单行(result = service.TheServiceMethod();),则使用DispatcherSynchronizationContext正确调用ServiceContinuation.
一个注意事项 - SynchronizationContext不会永久丢失 - 如果我再次单击该按钮,则按钮单击处理程序确实具有正确的SynchronizationContext.
我已经捕获了两个案例的堆栈跟踪; …
我有一个带有简单Web服务的ASP.NET 4.0 WebForms页面WebMethod.此方法用作异步/ TPL代码的同步包装器.我面临的问题是,内部Task有时会有一个null SynchronizationContext(我的偏好),但有时会有一个同步上下文System.Web.LegacyAspNetSynchronizationContext.在我提供的示例中,这并不会导致问题,但在我的实际开发场景中可能会导致死锁.
对服务的第一次调用似乎总是使用空同步上下文运行,接下来的几个也可能.但是一些快速激活的请求会开始弹出ASP.NET同步上下文.
[WebMethod]
public static string MyWebMethod(string name)
{
var rnd = new Random();
int eventId = rnd.Next();
TaskHolder holder = new TaskHolder(eventId);
System.Diagnostics.Debug.WriteLine("Event Id: {0}. Web method thread Id: {1}",
eventId,
Thread.CurrentThread.ManagedThreadId);
var taskResult = Task.Factory.StartNew(
function: () => holder.SampleTask().Result,
creationOptions: TaskCreationOptions.None,
cancellationToken: System.Threading.CancellationToken.None,
scheduler: TaskScheduler.Default)
.Result;
return "Hello " + name + ", result is " + taskResult;
}
Run Code Online (Sandbox Code Playgroud)
存在的定义TaskHolder:
public class TaskHolder …Run Code Online (Sandbox Code Playgroud) asp.net synchronizationcontext task-parallel-library webmethod async-await
在以前的MonoTouch版本中,我曾经这样做忽略了未观察到的异常:
TaskScheduler.UnobservedTaskException += delegate(object sender, UnobservedTaskExceptionEventArgs e) {
Console.WriteLine (e);
e.SetObserved ();
};
Run Code Online (Sandbox Code Playgroud)
这是否是一个好的做法是有争议的,但我想知道与Xamarin.iOS 6.4中正式支持的async/awaitkeywords 一起实现相同的效果.
这是我用于测试的代码:
async void OnClick (object sender, EventArgs e)
{
await Task.Run (() => { throw new Exception (); });
}
Run Code Online (Sandbox Code Playgroud)
当我运行它时,调试器暂停AsyncVoidMethodBuilder:

我读到.NET 4.5据说改变了行为,因此未观察到的异常不会使应用程序崩溃 - 但是如果将异常发布到UIKit同步上下文中我无法处理它们,这无济于事.
有没有办法忽略awaitMonoTouch中未观察到的异常?
我的团队正在使用C#5.0中的async/await开发一个多线程应用程序.在实现线程同步的过程中,经过几次迭代,我们想出了一个(可能是新颖的?)新的SynchronizationContext实现,它有一个内部锁:
在所有情况下,在执行委托之前,上下文将自身设置为当前上下文,并在委托返回时恢复原始上下文.
这是一个不寻常的模式,因为我们显然不是第一个写这样的应用程序的人,我想知道:
这是SerializingSynchronizationContext的源代码和GitHub上的一个演示.
以下是它的使用方法:
上下文是可以接受的,因此可以使用以下语句.
await myContext;
这只会导致方法的其余部分在上下文的保护下运行.
我试图找出在这种情况下使用的SemaphoreSlim使用Wait和WaitAsync之间的区别:
private SemaphoreSlim semaphore = new SemaphoreSlim(1);
public async Task<string> Get()
{
// What's the difference between using Wait and WaitAsync here?
this.semaphore.Wait(); // await this.semaphore.WaitAsync()
string result;
try {
result = this.GetStringAsync();
}
finally {
this.semaphore.Release();
}
return result;
}
Run Code Online (Sandbox Code Playgroud) async-await ×6
c# ×6
.net ×2
task ×2
wcf ×2
asp.net ×1
asp.net-core ×1
c#-5.0 ×1
concurrency ×1
semaphore ×1
webmethod ×1
wpf ×1
xamarin.ios ×1