在c#中从getter或setter调用异步方法的最优雅的方式是什么?
这里有一些伪代码来帮助我解释。
async Task<IEnumerable> MyAsyncMethod()
{
return await DoSomethingAsync();
}
public IEnumerable MyList
{
get
{
//call MyAsyncMethod() here
}
}
在c#中从getter或setter调用异步方法的最优雅的方式是什么?
这里有一些伪代码来帮助我解释。
async Task<IEnumerable> MyAsyncMethod()
{
return await DoSomethingAsync();
}
public IEnumerable MyList
{
get
{
//call MyAsyncMethod() here
}
}
当前回答
Necromancing。 在。net Core/NetStandard2中,你可以使用Nito.AsyncEx.AsyncContext.Run来代替System.Windows.Threading.Dispatcher.InvokeAsync:
class AsyncPropertyTest
{
private static async System.Threading.Tasks.Task<int> GetInt(string text)
{
await System.Threading.Tasks.Task.Delay(2000);
System.Threading.Thread.Sleep(2000);
return int.Parse(text);
}
public static int MyProperty
{
get
{
int x = 0;
// https://stackoverflow.com/questions/6602244/how-to-call-an-async-method-from-a-getter-or-setter
// https://stackoverflow.com/questions/41748335/net-dispatcher-for-net-core
// https://github.com/StephenCleary/AsyncEx
Nito.AsyncEx.AsyncContext.Run(async delegate ()
{
x = await GetInt("123");
});
return x;
}
}
public static void Test()
{
System.Console.WriteLine(System.DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss.fff"));
System.Console.WriteLine(MyProperty);
System.Console.WriteLine(System.DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss.fff"));
}
}
如果你只是选择System.Threading.Tasks.Task. run或System.Threading.Tasks.Task<int>。跑吧,那就没用了。
其他回答
因为你的“async属性”在一个视图模型中,你可以使用AsyncMVVM:
class MyViewModel : AsyncBindableBase
{
public string Title
{
get
{
return Property.Get(GetTitleAsync);
}
}
private async Task<string> GetTitleAsync()
{
//...
}
}
它将负责同步上下文和属性更改通知。
你可以简单地这样做:
public IEnumerable MyList
{
get
{
Task.Run(async () => await MyAsyncMethod);
}
}
但根据完整的上下文,你可以尝试找到另一种方式来触发你的异步方法,例如:当你调用MyList时,你可以调用第一个MyAsyncMethod..
由于我的解耦架构,我确实需要调用源自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");
}
}
}
我认为我们可以等待的值只是返回第一个空,然后得到真实的值,所以在纯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();
}
你可以像这样使用Task:
public int SelectedTab
{
get => selected_tab;
set
{
selected_tab = value;
new Task(async () =>
{
await newTab.ScaleTo(0.8);
}).Start();
}
}