这是一个两部分问题:
有人可以提供ASP.NET/.NET属性的列表,这些属性通常是与ExecutionContext一起流动的线程本地吗?
HttpContext.Current?Thread.CurrentContext?Thread.CurrentPrincipal中?Thread.CurrentCulture?
我可以依靠什么属性来存活/持续异步/等待?
还有什么?
有没有办法添加将使用ExecutionContext自动流动的特定于应用程序的上下文信息?就像是
var ec = ExecutionContext.Capture();
ec.CustomContext["MyCustomContext"] = ACustomContext;
Run Code Online (Sandbox Code Playgroud)如何判断由 发起的延续TaskCompletionSource.TrySetResult是同步执行还是异步执行?
例如:
// class A
void RegisterNotification(TaskCompletionSource<object> tcs)
{
this.source.NotificationEvent += (s, eData) =>
{
Debug.WriteLine("A.before");
tcs.TrySetResult(eData.Result);
Debug.WriteLine("A.after");
DoProcessingA();
};
}
// class B
async Task RequestNotificationAsync()
{
var tcs = new TaskCompletionSource<object>();
this.a.RegisterNotification(tcs);
Debug.WriteLine("B.before");
var data = await tcs.Task;
Debug.WriteLine("B.after");
DoProcessingB();
}
Run Code Online (Sandbox Code Playgroud)
如果在NotificationEvent具有与发生位置不同的同步上下文的线程上触发await tcs.Task,则调试输出将为:
B.之前 A.之前 A.之后 B.之后
也就是说,await tcs.Task延续是异步执行的。如果它在同一个同步上下文上触发(或者如果两个地方都没有同步上下文),则输出将为:
B.之前 A.之前 B.之后 A.之后
也就是说,延续是同步执行的。
有没有办法预测里面的这个顺序RegisterNotification?
我可以保存SynchronizationContext.Current在里面RegisterNotification,稍后打电话时进行比较tcs.TrySetResult。但这并不一定意味着这await tcs.Task将发生在我保存的上下文中。
理论上,如果我能预测这一点,我也许能够用它来诊断和防止潜在的死锁。
c# multithreading asynchronous task-parallel-library async-await
我最近写了以下代码:
Task<T> ExecAsync<T>( string connectionString, SqlCommand cmd, Func<SqlCommand, T> resultBuilder, CancellationToken cancellationToken = default(CancellationToken) )
{
var tcs = new TaskCompletionSource<T>();
SqlConnectionProvider p;
try
{
p = GetProvider( connectionString );
Task<IDisposable> openTask = p.AcquireConnectionAsync( cmd, cancellationToken );
openTask
.ContinueWith( open =>
{
if( open.IsFaulted ) tcs.SetException( open.Exception.InnerExceptions );
else if( open.IsCanceled ) tcs.SetCanceled();
else
{
var execTask = cmd.ExecuteNonQueryAsync( cancellationToken );
execTask.ContinueWith( exec =>
{
if( exec.IsFaulted ) tcs.SetException( exec.Exception.InnerExceptions );
else if( exec.IsCanceled ) tcs.SetCanceled();
else
{
try
{ …Run Code Online (Sandbox Code Playgroud) 我理解等待任务的异步会将执行返回给调用者,允许它继续直到需要结果.
我对我的想法的解释是正确的,直到某一点为止.看起来似乎正在进行某种交错.我希望Do3()完成,然后将调用堆栈备份到Do2().查看结果.
await this.Go();
Run Code Online (Sandbox Code Playgroud)
哪个电话
async Task Go()
{
await Do1(async () => await Do2("Foo"));
Debug.WriteLine("Completed async work");
}
async Task Do1(Func<Task> doFunc)
{
Debug.WriteLine("Start Do1");
var t = Do2("Bar");
await doFunc();
await t;
}
async Task Do2(string id)
{
Debug.WriteLine("Start Do2: " + id);
await Task.Yield();
await Do3(id);
Debug.WriteLine("End Do2: " + id);
}
async Task Do3(string id)
{
Debug.WriteLine("Start Do3: " + id);
await Task.Yield();
Debug.WriteLine("End Do3: " + id); // I did not expect Do2 to execute …Run Code Online (Sandbox Code Playgroud)