为什么在构造函数中不能使用await运算符?

时间:2016-03-04 22:26:10

标签: c# asynchronous constructor async-await

试图在构造函数中使用await属性调用异步方法,导致出现问题:

  public  MainPage()
    {

        view = new View();
        FacebookApiHandler FacebookApiHandler = new FacebookApiHandler(view);
        await FacebookApiHandler.getAccessByLogin();
        SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
        this.InitializeComponent();
    }

所以我的两个问题:

  • 为什么不能在cunstructor中使用await调用?
  • 还应该在哪里进行通话?

2 个答案:

答案 0 :(得分:1)

构造函数应该立即创建一个对象。通过使用await,不确定操作何时结束。它甚至不能确定它会完成。

您的课程似乎是一个GUI页面。这些通常有Initialized之类的事件。你应该把你的异步代码放在那里。

答案 1 :(得分:1)

通常,如果你正在使用某种类型的UI控件,如果你有一些需要完成的异步工作,你可以把它放在Loaded事件或其他类似的等价物中。

另一种选择是在构造函数中启动异步操作并在Task中保留引用,然后在您的方法中需要执行await的异步工作。如果任务没有完成,它将返回到等待的调用者,任务完成后它就会同步继续。

你不能在构造函数中await的原因是构造函数构建的对象必须准备好在构造函数的末尾分配,他们不希望你有一个“半完成”对象,因为您需要一种方法来跟踪它是否完全完成。

如果你真的需要构造函数中的类,最后一个解决方法是你有一个静态工厂方法来制作你的对象。这实际上只是隐藏了选项#2的实现。

public MainPage : Page
{
    protected  MainPage()
    {
        view = new View();
        _initTask = Init()
    }

    private async Task Init()
    {
        FacebookApiHandler FacebookApiHandler = new FacebookApiHandler(view);
        await FacebookApiHandler.getAccessByLogin();
        SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
        this.InitializeComponent();
    }

    private Task _initTask.

    public static Task<MainPage> CreatePageAsync()
    {
         var page = new MainPage();
         await page._initTask;
         return page;
    }
}

//Elsewhere
private async Task MyCode()
{
     MainPage page = await MainPage.CreatePageAsync();
}