我是否需要停止在UI线程中运行的方法?

时间:2017-07-21 12:45:21

标签: xamarin xamarin.forms

我的应用程序如下所示:

App类:

protected override void OnStart()
{
   MainPage = new Japanese.MainPage();
}

MainPage类:

var phrasesPage = new NavigationPage(new PhrasesPage())
{
   Title = "Play",
   Icon = "play.png"
};
Children.Add(phrasesPage);

PhrasesPage类:

protected override void OnAppearing()
{
   base.OnAppearing();
   phrasesFrame = new PhrasesFrame(this);
   phrasesStackLayout.Children.Add(phrasesFrame);
}

protected override void OnDisappearing()
{
   base.OnDisappearing();
   phrasesStackLayout.Children.Remove(phrasesFrame);
}

PhrasesFrame类:

public PhrasesFrame(PhrasesPage phrasesPage)
{
   InitializeComponent();
   Device.BeginInvokeOnMainThread(() => ShowCards().ContinueWith((arg) => { }));
}

public async Task ShowCards()
{
   while (true)
   {
      // information displayed on screen here and screen
      // responds to user clicks
      await Task.Delay(1000);
    }
}

这里有两个问题。

首先,我的ShowCards方法没有返回,因为它循环,直到用户点击屏幕底部的另一个图标来选择另一个屏幕。在这种情况下,我应该为返回值编码什么。因为它是IDE警告方法永远不会到达结束或返回语句。我该如何解决这个问题。

第二个相关问题。由于ShowCards在另一个线程上运行,当用户点击另一个图标以显示另一个屏幕时,我应该做些什么来取消它。

我希望有人可以帮我一些建议。请问是否有不清楚的地方,以便我可以尝试更清楚地提出问题。感谢

2 个答案:

答案 0 :(得分:8)

IDE警告您方法永远不会到达终点,因为它确实永远不会到达终点,并且正如编写的那样,您的任务将永远运行(或者至少在应用程序关闭之前)。

允许正在运行的任务被中断的标准方法是在创建任务时提供CancellationToken。您从CancellationTokenSource获取令牌,将令牌提供给任务,然后在Cancel()上调用CancellationTokenSource以将CancellationToken.IsCancellationRequested属性设置为true,指示任务它应该结束。

在你的情况下你可以有类似的东西:

CancellationTokenSource cts new CancellationTokenSource();

public PhrasesFrame(PhrasesPage phrasesPage)
{
   InitializeComponent();
   Device.BeginInvokeOnMainThread(() => ShowCards(cts.Token).ContinueWith((arg) => { }));
}

public Disappearing() {
    cts.Cancel();
}

public async Task ShowCards(CancellationToken ct)
{
   while (!ct.IsCancellationRequested)
   {
      // information displayed on screen here and screen
      // responds to user clicks
      await Task.Delay(1000, ct);
    }
}

然后在您希望结束任务时调用Disappearing(),例如在您的PhrasesPage方法中:

protected override void OnDisappearing()
{
   base.OnDisappearing();
   phrasesFrame.Disappearing();
   phrasesStackLayout.Children.Remove(phrasesFrame);
}

答案 1 :(得分:0)

您可以使用取消令牌创建任务,当您转到后台时,您可以取消此令牌。

您可以在PCL https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/app-lifecycle/

中执行此操作
var cancelToken = new CancellationTokenSource();
Task.Factory.StartNew(async () => {
    await Task.Delay(10000);
    // call web API
}, cancelToken.Token);

//this stops the Task:
cancelToken.Cancel(false);

Anther解决方案是Xamarin.Forms中的用户计时器,可以在需要时停止计时器 https://xamarinhelp.com/xamarin-forms-timer/