我有一个可以运行的应用程序,但过一会儿,当我在iPhone上调试时,它挂起了手机,并且唯一可以恢复的方法是硬性重置侧面的按钮和主页按钮。
首先,那可能是因为我的应用程序存在内存泄漏吗?
这是该应用程序的代码。特别是,我正在查看BeginInvokeOnMainThread
方法。有人可以告诉我是否可以看到实现方式是否有问题?另外,.ContinueWith((arg)
的目的是什么。
namespace Japanese
{
public partial class PhrasesFrame : Frame
{
CancellationTokenSource cts = new CancellationTokenSource();
public PhrasesFrame(PhrasesPage phrasesPage)
{
InitializeComponent();
this.phrasesPage = phrasesPage;
AS.phrasesFrame = this;
Device.BeginInvokeOnMainThread(() => ShowCards(cts.Token).ContinueWith((arg) => { }));
}
public void Disappearing()
{
cts.Cancel();
}
public async Task ShowCards(CancellationToken ct)
{
AS.cardCountForSelectedCategories = App.DB.GetCardCountForSelectedCategories();
while (!ct.IsCancellationRequested)
{
await Task.Delay(500);
}
}
}
}
最佳答案
继续
首先,让我们解决有关.ContinueWith((arg) => { }))
的问题。原始ContinueWith
完成后,Task
告诉更多代码要执行。在我们的例子中,ContinueWith
完成后,Device.BeginInvokeOnMainThread(() => ShowCards(cts.Token)
内部的代码将运行。
在这种情况下,ContinueWith
内没有任何代码,因此我们可以将其删除。
冷冻
是的,我可以看到这段代码有可能卡住UI。BeginInvokeOnMainThread
将使Action
排队以在主线程(也称为UI线程)上运行。主线程一直在监听用户的输入(点击屏幕上的按钮,捏缩放等),如果该线程正忙于执行长时间运行的任务,它将无法响应用户的输入。输入直到完成;因此您的应用将显示为卡住状态。
主线程正在调用代码await Task.Delay(500);
。因此,我们告诉主线程将自身卡住500毫秒,并无限循环。
一种解决方案是将该代码包装在Task.Run
中,将其放在后台线程中,并释放主线程以监听/响应用户输入。
Task.Run(async () =>
{
while (!ct.IsCancellationRequested)
{
await Task.Delay(500);
}
}
更多线程建议
BeginInvokeOnMainThread
。 99%的代码可以在后台线程上运行而没有问题。 1%是用于更新UI的代码。任何更新UI的代码都必须在主线程上运行。 await Task.Run(() => AS.cardCountForSelectedCategories = App.DB.GetCardCountForSelectedCategories());