我期待在1.2位回到第1号线,但我没有。有没有办法在进行异步调用后返回UI线程?感谢
另外我无法使顶级方法异步。不确定异步是否会解决这个问题,但我现在没有那个选择。
class Program
{
static void Main(string[] args)
{
ComputeThenUpdateUI().Wait();
}
static async Task ComputeThenUpdateUI()
{
Console.WriteLine($"1.1 {Thread.CurrentThread.ManagedThreadId}");
await ExpensiveComputingNonUI().ConfigureAwait(true);
Console.WriteLine($"1.2 {Thread.CurrentThread.ManagedThreadId}");
}
static async Task ExpensiveComputingNonUI()
{
Console.WriteLine($"2.1 {Thread.CurrentThread.ManagedThreadId}");
await Task.Delay(3000).ConfigureAwait(false);
Console.WriteLine($"2.2 {Thread.CurrentThread.ManagedThreadId}");
await Task.Delay(3000).ConfigureAwait(false);
Console.WriteLine($"2.3 {Thread.CurrentThread.ManagedThreadId}");
}
}
Output:
1.1 1
2.1 1
2.2 4
2.3 4
1.2 4
答案 0 :(得分:3)
Re:public static async Task Main(string[] args)
{
// Can await asynchronous tasks here.
}
是否意味着await完成后流将返回到同一个线程?
不,在大多数情况下,没有保证。 Stephen Cleary有一个明确的答案:
这个“上下文”是SynchronizationContext.Current,除非它是null,在这种情况下它是TaskScheduler.Current。 (如果当前没有正在运行的任务,则TaskScheduler.Current与TaskScheduler.Default(线程池任务调度程序)相同。)
重要的是要注意SynchronizationContext或TaskScheduler并不一定意味着特定的线程。 UI SynchronizationContext将为UI线程安排工作;但是ASP.NET SynchronizationContext不会为特定线程安排工作。
即。仅从例如UI线程进行的调用。 WPF或Windows窗体保证返回到同一个线程。如果你真的需要返回同一个帖子,那么你需要做customization to ensure the continuation is scheduled on the original thread。
除非这是必要的(例如UI线程),否则返回同一个线程通常是不受欢迎的,因为这会降低性能(如果存在争用线程)和lead to deadlocks
Re:无法使顶级主要方法异步
现在可以在C#7.1:
中使用input(type='hidden', name='_csrf', value=_csrf)
答案 1 :(得分:1)
ConfigureAwait
是您编写的每个方法中的本地决定。 ConfigureAwait(true)
是一种表示您希望尝试返回首次输入方法时运行方法的的方法。
首先,这意味着如果你不知道你最初在中运行的是什么上下文,那么尝试回到相同的上下文并没有太大的意义。如果可以在各种上下文中调用,则不应尝试执行与上下文相关的任何操作。这就是为什么如果你正在创作一个库,使用ConfigureAwait(false)
通常是个好建议。您不会知道调用代码的上下文。
其次,这意味着没有“全球”背景可以回归。如果您的调用者(或者其中任何一个调用者等,在链的上方)已经将自己与他们的原始调用上下文分开,那么就没有办法(通过这个机制)来回到那个背景。
如果要切换到特定的上下文(例如UI线程)并且不能保证是您的调用上下文,则需要使用不同的特定于上下文的机制,例如Dispatcher.Invoke()
或适合您环境的任何内容。