等待Windows Store App和Windows Phone App后的不同线程......?

And*_*ord 0 c# async-await windows-phone-8 windows-store-apps

我正在将Windows Phone应用程序移植到Windows 8,我遇到了async/await问题.有一个类需要一段时间才能加载其所有数据.为了不阻止UI线程,加载在单独的任务/线程中完成.加载完成后,需要更新UI线程:

public class MyClass {
   public MyClass() {
      ...
      LoadData();
      ...
   }

   private async void LoadData() {
      Debug.WriteLine("StartLoad: " + Environment.CurrentManagedThreadId);
      await ReadDataAsync();
      Debug.WriteLine("EndLoad: " + Environment.CurrentManagedThreadId);

      UpdateUI();
   }

   private Task ReadDataAsync() {
      return Task.Run(() => {
         Debug.WriteLine("Reading: " + Environment.CurrentManagedThreadId);
         ...Read...
      });
   }
} 
Run Code Online (Sandbox Code Playgroud)

在Windows Phone上,输出是这样的:

StartLoad:1

阅读:4

EndLoad:1

当我在Windows应用商店应用中执行相同的代码时,输​​出为:

StartLoad:1

阅读:4

EndLoad:4

在Windows Phone上,ThreadId是相同的,在等待Windows 8之后,await之后的ThreadId与await之前的不一样.这是与后台任务中相同的线程.由于这个UpdateUI()在错误的(非UI)线程中执行,应用程序崩溃...

这种不同行为的原因是什么?

..

编辑: 嗯,这很有趣:尽管在这两种情况下,进程都是从同一个线程(3)开始的,但问题只会在进程从App()构造函数启动时显示,而不是从OnLaunched启动时显示.知道为什么会这样吗?

sealed partial class App : Application {
    public App() {            
        this.InitializeComponent();
        this.Suspending += OnSuspending;

        Debug.WriteLine("App: " + Environment.CurrentManagedThreadId);

        MyClass test = new MyClass();                 
    }

    protected override async void OnLaunched(LaunchActivatedEventArgs e) {
        Debug.WriteLine("OnLaunched: " + Environment.CurrentManagedThreadId);

        MyClass test = new MyClass();
    }
}
Run Code Online (Sandbox Code Playgroud)

这会创建:

应用程序:3

StartLoad:3

阅读:4

EndLoad:4

OnLaunched:3

StartLoad:3

阅读:5

EndLoad:3

Ser*_*rvy 5

您正在运行最终将启动应用程序消息循环的线程中的代码,但在那个时间点尚未执行此操作.该SynchronizationContext表示UI还没有被创建并设置为当前上下文.因此,该async方法没有上下文来捕获并在每个之后发送延续await; 改为使用默认上下文,将延续发送到线程池.

一旦SynchronizationContext已经设置好,您需要稍后运行代码.这就是为什么它在你打电话时起作用的原因OnLaunched; 在设置上下文后运行.

如果你看一下它的值SynchronizationContext.Current,你会发现它在你的第一种情况下是空的,并且在第二种情况下有一个值.这不是检查当前线程的ID,而是更好地指示continuation是否能够在UI线程中运行.