コンストラクタは非同期にできますか? 質問する

コンストラクタは非同期にできますか? 質問する

コンストラクターにデータを入力しようとしているプロジェクトがあります。

public class ViewModel
{
    public ObservableCollection<TData> Data { get; set; }

    async public ViewModel()
    {
        Data = await GetDataTask();
    }

    public Task<ObservableCollection<TData>> GetDataTask()
    {
        Task<ObservableCollection<TData>> task;

        //Create a task which represents getting the data
        return task;
    }
}

残念ながら、エラーが発生します:

このアイテムには修飾子はasync無効です

もちろん、標準メソッドをラップしてコンストラクターから呼び出す場合は次のようになります。

public async void Foo()
{
    Data = await GetDataTask();
}

問題なく動作します。同様に、古い裏返しの方法を使用すると

GetData().ContinueWith(t => Data = t.Result);

これも機能します。なぜコンストラクター内から直接呼び出せないのか疑問に思っていましたawait。おそらく、それに反するエッジケースや理由がたくさんあると思いますが、私には思いつきません。説明を探してみましたが、何も見つからないようです。

ベストアンサー1

非同期コンストラクターを作成することはできないため、プライベート コンストラクターによって作成されたクラス インスタンスを返す静的非同期メソッドを使用します。これはエレガントではありませんが、問題なく動作します。

public class ViewModel       
{       
    public ObservableCollection<TData> Data { get; set; }       

    //static async method that behave like a constructor       
    async public static Task<ViewModel> BuildViewModelAsync()  
    {       
        ObservableCollection<TData> tmpData = await GetDataTask();  
        return new ViewModel(tmpData);
    }       

    // private constructor called by the async method
    private ViewModel(ObservableCollection<TData> Data)
    {
        this.Data = Data;   
    }
}  

おすすめ記事