ContinueWith loses the SynchronizationContext
本文关键字:SynchronizationContext the loses ContinueWith | 更新日期: 2023-09-27 17:59:14
在下面的代码段中,SynchronizationContext
丢失了,因此CurrentCulture
和CurrentUICulture
也丢失了。CCD_ 4就是来自这个答案。
public async Task<ActionResult> Index()
{
Log("before GetAsync");
await new HttpClient().GetAsync("http://www.example.com/")
.ContinueWith(request =>
{
Log("ContinueWith");
request.Result.EnsureSuccessStatusCode();
}, TaskContinuationOptions.AttachedToParent);
return View();
}
static void Log(string message)
{
var ctx = System.Threading.SynchronizationContext.Current;
System.Diagnostics.Debug.Print("{0}; thread: {1}, context: {2}, culture: {3}, uiculture: {4}",
message,
System.Threading.Thread.CurrentThread.ManagedThreadId,
ctx != null ? ctx.GetType().Name : String.Empty,
System.Threading.Thread.CurrentThread.CurrentCulture.Name,
System.Threading.Thread.CurrentThread.CurrentUICulture.Name);
}
这是输出:
在GetAsync之前;线程:56,上下文:AspNetSynchronizationContext,文化:nl,ui文化:nl
ContinueWith;线程:46,上下文:,文化:nl-BE,uiculture:en-US
在GetAsync
之前,区域性和UI区域性具有我在Application_BeginRequest
中设置的值。在ContinueWith
中,上下文丢失,区域性被设置为浏览器提供的内容,UI区域性被设为某些默认值。
据我所知,AspNetSynchronizationContext
的一切都应该自动发生。我的代码出了什么问题?
为了在请求上下文线程上强制调度延续,您需要指定在调度延续时应使用的TaskScheduler
。
public async Task<ActionResult> Index()
{
Log("before GetAsync");
await new HttpClient().GetAsync("http://www.example.com/")
.ContinueWith(request =>
{
Log("ContinueWith");
request.Result.EnsureSuccessStatusCode();
},
TaskContinuationOptions.AttachedToParent,
CancellationToken.None,
TaskScheduler.FromCurrentSynchronizationContext());
return View();
}
但是,您使用的是await
,它会自动将延续封送至当前的SynchronizationContext
。你应该能够做到这一点:
public async Task<ActionResult> Index()
{
Log("before GetAsync");
HttpResponseMessage request = await new HttpClient().GetAsync("http://www.example.com/");
//everything below here is you 'continuation' on the request context
Log("ContinueWith");
request.EnsureSuccessStatusCode();
return View();
}
您尝试过TaskContinuationOptions.ExecuteSynchronously
吗?它应该在同一个线程中运行延续任务。。。
http://msdn.microsoft.com/en-us/library/vstudio/system.threading.tasks.taskcontinuationoptions
"指定应同步执行延续任务。指定此选项后,延续将在导致先行任务转换到其最终状态的同一线程上运行。如果创建延续时先行任务已经完成,则延续将在创建延续的线程上运行同步执行。"