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

时间:2014-01-09 15:03:24

标签: c# windows-phone-8 windows-store-apps async-await

我正在将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...
      });
   }
} 

在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();
    }
}

这会创建:

  

App:3

     

StartLoad:3

     

阅读:4

     

EndLoad: 4

     

OnLaunched:3

     

StartLoad:3

     

阅读:5

     

EndLoad: 3

2 个答案:

答案 0 :(得分:5)

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

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

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

答案 1 :(得分:0)

最可能的原因是实际上没有在UI线程上调用LoadData