Kaa*_*rak 158 c# constructor async-await windows-phone-8 visual-studio-2013
简介:我想在构造函数中调用异步方法.这可能吗?
详细信息:我有一个调用getwritings()
JSON数据的方法.如果我只是调用getwritings()
一个async
方法并将其放在await
左侧,那么一切正常.但是,当我LongListView
在我的页面中创建一个并尝试填充它时,我发现这getWritings()
是令人惊讶的返回null
而且LongListView
是空的.
为了解决这个问题,我尝试更改getWritings()
to 的返回类型,Task<List<Writing>>
然后在构造函数中检索结果getWritings().Result
.但是,这样做最终会阻止UI线程.
public partial class Page2 : PhoneApplicationPage
{
List<Writing> writings;
public Page2()
{
InitializeComponent();
getWritings();
}
private async void getWritings()
{
string jsonData = await JsonDataManager.GetJsonAsync("1");
JObject obj = JObject.Parse(jsonData);
JArray array = (JArray)obj["posts"];
for (int i = 0; i < array.Count; i++)
{
Writing writing = new Writing();
writing.content = JsonDataManager.JsonParse(array, i, "content");
writing.date = JsonDataManager.JsonParse(array, i, "date");
writing.image = JsonDataManager.JsonParse(array, i, "url");
writing.summary = JsonDataManager.JsonParse(array, i, "excerpt");
writing.title = JsonDataManager.JsonParse(array, i, "title");
writings.Add(writing);
}
myLongList.ItemsSource = writings;
}
}
Run Code Online (Sandbox Code Playgroud)
Ste*_*ary 111
最好的解决方案是承认下载和设计的异步性质.
换句话说,在下载数据时确定应用程序的外观.让页面构造函数设置该视图,然后开始下载.下载完成后,更新页面以显示数据.
我有一篇关于异步构造函数的博客文章,你可能会发现它很有用.还有一些MSDN文章; 一个用于异步数据绑定(如果您使用的是MVVM),另一个用于异步最佳实践(即,您应该避免async void
).
Pet*_*nar 71
你也可以这样做:
Task.Run(() => this.FunctionAsync()).Wait();
Run Code Online (Sandbox Code Playgroud)
Sha*_*azi 51
我想分享一种我一直用来解决这些问题的模式.我觉得它运作得相当好.当然,它只有在你控制了什么调用构造函数时才有效.以下示例
public class MyClass
{
public static async Task<MyClass> Create()
{
var myClass = new MyClass();
await myClass.Initialize();
return myClass;
}
private MyClass()
{
}
private async Task Initialize()
{
await Task.Delay(1000); // Do whatever asynchronous work you need to do
}
}
Run Code Online (Sandbox Code Playgroud)
基本上我们所做的是将构造函数设为私有,并创建我们自己的公共静态异步方法,该方法负责创建MyClass的实例.通过使构造函数私有并将静态方法保持在同一个类中,我们确保没有人可以"无意中"创建此类的实例而无需调用正确的初始化方法.围绕对象创建的所有逻辑仍然包含在类中(仅在静态方法中).
var myClass1 = new MyClass() // Cannot be done, the constructor is private
var myClass2 = MyClass.Create() // Returns a Task that promises an instance of MyClass once it's finished
var myClass3 = await MyClass.Create() // asynchronously creates and initializes an instance of MyClass
Run Code Online (Sandbox Code Playgroud)
在当前场景中实现它看起来像:
public partial class Page2 : PhoneApplicationPage
{
public static async Task<Page2> Create()
{
var page = new Page2();
await page.getWritings();
return page;
}
List<Writing> writings;
private Page2()
{
InitializeComponent();
}
private async Task getWritings()
{
string jsonData = await JsonDataManager.GetJsonAsync("1");
JObject obj = JObject.Parse(jsonData);
JArray array = (JArray)obj["posts"];
for (int i = 0; i < array.Count; i++)
{
Writing writing = new Writing();
writing.content = JsonDataManager.JsonParse(array, i, "content");
writing.date = JsonDataManager.JsonParse(array, i, "date");
writing.image = JsonDataManager.JsonParse(array, i, "url");
writing.summary = JsonDataManager.JsonParse(array, i, "excerpt");
writing.title = JsonDataManager.JsonParse(array, i, "title");
writings.Add(writing);
}
myLongList.ItemsSource = writings;
}
}
Run Code Online (Sandbox Code Playgroud)
而不是做
var page = new Page2();
Run Code Online (Sandbox Code Playgroud)
你会做的
var page = await Page2.Create();
Run Code Online (Sandbox Code Playgroud)
我的首选方法:
// caution: fire and forget
Task.Run(async () => await someAsyncFunc());
Run Code Online (Sandbox Code Playgroud)
在任何构造函数中执行一些耗时操作的一种快速方法是创建一个操作并异步运行它们。
new Action( async() => await InitializeThingsAsync())();
Run Code Online (Sandbox Code Playgroud)
运行这段代码既不会阻塞你的 UI,也不会留下任何松散的线程。如果您需要更新任何 UI(考虑到您没有使用 MVVM 方法),您可以使用 Dispatcher 来按照许多人的建议进行更新。
A 注意:如果您没有任何init
oronload
或navigated
覆盖,则此选项仅提供一种从构造函数开始执行方法的方法。即使在施工完成后,这很可能会继续运行。因此,此方法调用的结果可能在构造函数本身中不可用。
尝试替换这个:
myLongList.ItemsSource = writings;
Run Code Online (Sandbox Code Playgroud)
有了这个
Dispatcher.BeginInvoke(() => myLongList.ItemsSource = writings);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
109997 次 |
最近记录: |