在C#中从getter或setter调用异步方法最优雅的方法是什么?
这里有一些伪代码可以帮助解释自己.
async Task<IEnumerable> MyAsyncMethod()
{
return await DoSomethingAsync();
}
public IEnumerable MyList
{
get
{
//call MyAsyncMethod() here
}
}
Run Code Online (Sandbox Code Playgroud)
Ste*_*ary 182
没有技术原因async
在C#中不允许使用属性.这是一个有目的的设计决策,因为"异步属性"是矛盾的.
属性应返回当前值; 他们不应该开始背景操作.
通常,当有人想要"异步属性"时,他们真正想要的是以下之一:
async
方法.async
工厂方法来包含对象,要么使用async InitAsync()
方法.数据绑定值将default(T)
一直到计算/检索该值.AsyncLazy
我的博客或AsyncEx库.这将为您提供一个有await
能力的财产.更新:我在我最近的一篇"异步OOP"博客文章中介绍了异步属性.
Ree*_*sey 91
您不能异步调用它,因为没有异步属性支持,只有异步方法.因此,有两个选项,都利用了CTP中的异步方法实际上只是一个返回的方法Task<T>
或Task
:
// Make the property return a Task<T>
public Task<IEnumerable> MyList
{
get
{
// Just call the method
return MyAsyncMethod();
}
}
Run Code Online (Sandbox Code Playgroud)
要么:
// Make the property blocking
public IEnumerable MyList
{
get
{
// Block via .Result
return MyAsyncMethod().Result;
}
}
Run Code Online (Sandbox Code Playgroud)
Dog*_*uca 48
由于我的解耦架构,我真的需要来自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");
}
}
}
Run Code Online (Sandbox Code Playgroud)
Moh*_*enB 11
你可以这样使用Task
:
public int SelectedTab
{
get => selected_tab;
set
{
selected_tab = value;
new Task(async () =>
{
await newTab.ScaleTo(0.8);
}).Start();
}
}
Run Code Online (Sandbox Code Playgroud)
Jua*_*llo 10
我认为我们可以等待只返回第一个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();
}
Run Code Online (Sandbox Code Playgroud)
我想.GetAwaiter().GetResult()正是这个问题的解决方案,不是吗?例如:
string _Title;
public string Title
{
get
{
if (_Title == null)
{
_Title = getTitle().GetAwaiter().GetResult();
}
return _Title;
}
set
{
if (value != _Title)
{
_Title = value;
RaisePropertyChanged("Title");
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
在.NET Core中你可以像这样使用它:
InvokeAsync(async () => { await MyAsyncMethod(); });
Run Code Online (Sandbox Code Playgroud)
所以完整的 getter/setter 应该是这样的:
private bool _myBoolProperty;
public bool MyBoolProperty
{
get { return _myBoolProperty; }
set
{
_myBoolProperty = value;
InvokeAsync(async () => { await MyAsyncMethod(); });
}
}
Run Code Online (Sandbox Code Playgroud)