C# でゲッターまたはセッターから非同期メソッドを呼び出す最もエレガントな方法は何ですか?
自分自身を説明するのに役立つ疑似コードを次に示します。
async Task<IEnumerable> MyAsyncMethod()
{
return await DoSomethingAsync();
}
public IEnumerable MyList
{
get
{
//call MyAsyncMethod() here
}
}
C# でプロパティが許可されないという技術的な理由はありません。async
「非同期プロパティ」は矛盾しているため、意図的な設計上の決定でした。
プロパティは現在の値を返す必要があります。バックグラウンド操作を開始するべきではありません。
通常、「非同期プロパティ」が必要な場合、実際に必要なのは次のいずれかです。
async
メソッドに変更します。async
含まれているオブジェクトのファクトリ メソッドを使用するか、メソッドを使用しasync InitAsync()
ます。データバインドさdefault(T)
れた値は、値が計算/取得されるまで続きます。AsyncLazy
私のブログまたはAsyncEx ライブラリから使用します。これにより、await
有能なプロパティが得られます。更新:最近の「非同期OOP 」ブログ投稿の 1 つで、非同期プロパティについて説明しています。
非同期プロパティはサポートされておらず、非同期メソッドのみがサポートされているため、非同期で呼び出すことはできません。Task<T>
そのため、2 つのオプションがあり、どちらも CTP の非同期メソッドは実際にはorを返すメソッドにすぎないという事実を利用していますTask
。
// Make the property return a Task<T>
public Task<IEnumerable> MyList
{
get
{
// Just call the method
return MyAsyncMethod();
}
}
または:
// Make the property blocking
public IEnumerable MyList
{
get
{
// Block via .Result
return MyAsyncMethod().Result;
}
}
アーキテクチャが分離されているため、getメソッドから発信する呼び出しが本当に必要でした。そこで、次の実装を思いつきました。
使用法: タイトルは、ページリソースとして静的に宣言できるViewModelまたはオブジェクトにあります。それにバインドすると、getTitle()が戻ったときに、UIをブロックせずに値が入力されます。
string _Title;
public string Title
{
get
{
if (_Title == null)
{
Deployment.Current.Dispatcher.InvokeAsync(async () => { Title = await getTitle(); });
}
return _Title;
}
set
{
if (value != _Title)
{
_Title = value;
RaisePropertyChanged("Title");
}
}
}
値が最初に null を返すのを待ってから実際の値を取得できると思うので、純粋な MVVM (たとえば PCL プロジェクト) の場合、次の方法が最もエレガントなソリューションだと思います。
private IEnumerable myList;
public IEnumerable MyList
{
get
{
if(myList == null)
InitializeMyList();
return myList;
}
set
{
myList = value;
NotifyPropertyChanged();
}
}
private async void InitializeMyList()
{
MyList = await AzureService.GetMyList();
}