und*_*ind 1 c# wpf asynchronous task async-await
假设我有一个简单的C#控制台应用程序:
class Program
{
static async void func()
{
Thread.CurrentThread.Name = "main";
await Task.Run(() =>
{
Thread.CurrentThread.Name = "child";
Thread.Sleep(5000);
});
Console.WriteLine("continuation is running on {0} thread", Thread.CurrentThread.Name);
}
static void Main(string[] args)
{
func();
Thread.Sleep(10000);
}
}
Run Code Online (Sandbox Code Playgroud)
当5000毫秒通过时,我们看到"继续在子线程上运行"消息.当另一个5000毫秒通过时,主线程完成其工作并关闭应用程序.它看起来很合乎逻辑:异步任务及其延续在同一子线程上运行.
但现在假设我有一个简单的WPF应用程序:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
async private void mainWnd_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Thread.CurrentThread.Name = "main";
await Task.Run(() =>
{
Thread.CurrentThread.Name = "child";
Thread.Sleep(5000);
});
this.Title = string.Format("continuation is running on {0} thread", Thread.CurrentThread.Name);
}
private void mainWnd_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
Thread.Sleep(10000);
}
}
Run Code Online (Sandbox Code Playgroud)
现在当我们按下鼠标左键并传递5000毫秒时,我们看到"继续在主线程上运行"标题.此外,如果我们按下左键然后按右键,应用程序首先运行mainWnd_MouseLeftButtonDown处理程序,然后mainWnd_MouseRightButtonDown处理程序(在主线程上),主线程将休眠10000毫秒,然后继续执行异步任务mainWnd_MouseLeftButtonDown将仍然在主线程上执行.
为什么async-await这两种情况的机制不同?
我知道在WPF方法中可以在UI线程上显式运行Dispatcher.Invoke,但async-await机制不是WPF特定的,所以它的行为应该在任何类型的应用程序中都相同,不应该吗?
任何帮助将不胜感激.
async-await尊重当前的范围SynchronizationContext.这意味着在异步操作开始时捕获上下文(如果存在),并且当它结束时,将在捕获的上下文上调度continuation.
UI应用程序(WPF/ Winforms)使用a SynchronizationContext只允许main(UI)线程与UI元素交互,因此它可以无缝地工作async-await.
ASP.Net也有它自己SynchronizationContext叫AspNetSynchronizationContext(令人惊讶).所以它不一定是关于UI或单线程公寓.
如果你想禁用那个有用的SynchronizationContext捕获,你只需要使用ConfigureAwait:
await Task.Run(() =>
{
Thread.CurrentThread.Name = "child";
Thread.Sleep(5000);
}).ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)
有关SynchronizationContexts的更多信息:它是关于SynchronizationContext的全部内容
| 归档时间: |
|
| 查看次数: |
1586 次 |
| 最近记录: |