nos*_*tio 12 .net c# task-parallel-library async-await
这是一个简单的WinForms应用程序:
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
var ts = TaskScheduler.FromCurrentSynchronizationContext();
await Task.Factory.StartNew(async () =>
{
Debug.WriteLine(new
{
where = "1) before await",
currentTs = TaskScheduler.Current,
thread = Thread.CurrentThread.ManagedThreadId,
context = SynchronizationContext.Current
});
await Task.Yield(); // or await Task.Delay(1)
Debug.WriteLine(new
{
where = "2) after await",
currentTs = TaskScheduler.Current,
thread = Thread.CurrentThread.ManagedThreadId,
context = SynchronizationContext.Current
});
}, CancellationToken.None, TaskCreationOptions.None, scheduler: ts).Unwrap();
}
}
}
Run Code Online (Sandbox Code Playgroud)
调试输出(单击按钮时):
{ where = 1) before await, currentTs = System.Threading.Tasks.SynchronizationContextTaskScheduler, thread = 9, context = System.Windows.Forms.WindowsFormsSynchronizationContext }
{ where = 2) after await, currentTs = System.Threading.Tasks.ThreadPoolTaskScheduler, thread = 9, context = System.Windows.Forms.WindowsFormsSynchronizationContext }
问题:为什么要在这之后TaskScheduler.Current改变?SynchronizationContextTaskSchedulerThreadPoolTaskSchedulerawait
这基本上表现出行为TaskCreationOptions.HideScheduler的await延续,这是意想不到的不良,在我看来.
这个问题是由我的另一个问题引发的:
Ste*_*ary 13
如果没有执行任何实际任务,则与之TaskScheduler.Current相同TaskScheduler.Default.换句话说,ThreadPoolTaskScheduler实际上既作为线程池任务调度程序又作为"无当前任务调度程序"的值.
async委托的第一部分是使用SynchronizationContextTaskScheduler,显式调度的,并在UI线程上运行,同时具有任务调度程序和同步上下文.任务调度程序将委托转发到同步上下文.
当await捕捉它的上下文,它抓住了同步上下文(而不是任务调度程序),并使用该syncctx恢复.因此,方法continuation被发布到syncctx,它在UI线程上执行它.
当延续在UI线程上运行时,它的行为与事件处理程序非常相似; 委托直接执行,不包含在任务中.如果你TaskScheduler.Current在开头检查button1_Click,你会发现它也是ThreadPoolTaskScheduler.
顺便说一句,我建议您将此行为(直接执行委托,不包含在任务中)视为实现细节.