Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 启动时执行异步任务_C#_Multithreading_Xamarin_Xamarin.forms_Async Await - Fatal编程技术网

C# 启动时执行异步任务

C# 启动时执行异步任务,c#,multithreading,xamarin,xamarin.forms,async-await,C#,Multithreading,Xamarin,Xamarin.forms,Async Await,我想使用Xamarin执行下一步: 当应用程序启动时,会立即显示splashScreen(我在下面的教程中实现了这一点) 执行数据库迁移(如果用户更新了应用程序并第一次运行它) 从数据库读取用户数据(用户名和密码),调用REST Web服务检查用户数据是否仍然有效。如果用户数据有效,则将用户重定向到主页,否则重定向到登录页面 我已经读了下一篇好文章。当前代码: public class MainActivity :global::Xamarin.Forms.Platform.Android.

我想使用Xamarin执行下一步:

  • 当应用程序启动时,会立即显示splashScreen(我在下面的教程中实现了这一点)

  • 执行数据库迁移(如果用户更新了应用程序并第一次运行它)

  • 从数据库读取用户数据(用户名和密码),调用REST Web服务检查用户数据是否仍然有效。如果用户数据有效,则将用户重定向到主页,否则重定向到登录页面

我已经读了下一篇好文章。当前代码:

public class MainActivity :global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
{
  protected override void OnCreate (Bundle bundle)
  {
    base.OnCreate (bundle);
    global::Xamarin.Forms.Forms.Init (this, bundle);
    LoadApplication (new App ()); // method is new in 1.3
  }
}

// shared code - PCL lib for Android and iOS
public partial class App : Application
{
  public App()
  {
    InitializeComponent();
    // MainPage = new LoadingPage();
  }
}    
protected override async void OnStart()
{
  // Handle when your app starts
  await App.Database.Migrations();
  if( await CheckUser()) // reads user data from db and makes http request
    this.MainPage = new Layout.BrowsePage();
  else
    this.MainPage = new LoginPage();
 }
如果未在构造函数中设置
MainPage
,则会在iOS和Android上引发异常。我知道,如果async void没有显式地具有
.wait()
- ,但这是否意味着执行线程仍然继续它的工作

执行线程时,点击
等待App.Database.Migrations()它暂停执行并等待等待任务完成。同时,它继续工作(即LoadApplication()继续执行,并希望App.MainPage现在已经设置好)。我的假设正确吗

我只想避免加载页面,因为显示了三个屏幕:

  • 启动屏幕(应用程序启动时的右侧)
  • 加载页面(数据库迁移、http请求等)
  • 浏览页面或登录页面
为了用户体验,最好只有两页

我的结局是这样的,但我相信有更好的方法:

protected override void OnStart()
{
  Page startPage = null;
  Task.Run(async() =>
  {
    await App.Database.Migrations();
    startPage = await CheckUser() ? new Layout.BrowsePage() : new LoginPage();
  }.Wait();
  this.MainPage = startPage();
}

另一种方法是将要并发运行的每个项目添加到任务列表中,然后等待所有任务。然后所有项目都将异步运行,但您仍然可以获得CheckUser的结果。我不知道它是否比你用的更好,但这是另一种方式。否则,如果您正在等待每个函数,则它们不会同时运行

    protected async Task OnStart()
    {
        Page startPage = null;
        //create a list of the items you want to run concurrently
        List<Task> list = new List<Task>();
        list.Add(App.Database.Migrations());
        list.Add(CheckUser());
        //wait for all of them to complete
        Task.WaitAll(list.ToArray());

        //get the result from the CheckUser call
        Task<bool> checkUsertask = list[1] as Task<bool>;
        if (checkUsertask.Result == true)
            this.MainPage = new Layout.BrowsePage();
        else
            this.MainPage = new LoginPage();
    }
受保护的异步任务启动()
{
页面起始页=空;
//创建要同时运行的项的列表
列表=新列表();
list.Add(App.Database.Migrations());
添加(CheckUser());
//等待它们全部完成
Task.WaitAll(list.ToArray());
//从CheckUser调用中获取结果
Task checkUsertask=将[1]列为任务;
if(checkUsertask.Result==true)
this.MainPage=newlayout.BrowsePage();
其他的
this.MainPage=新登录页面();
}
如果您不喜欢列表[1],则可以在将其添加到列表之前创建一个任务,以便在完成后可以参考它

protected async Task OnStart()
{
    Page startPage = null;
    //create a list of the items you want to run concurrently
    List<Task> list = new List<Task>();
    list.Add(App.Database.Migrations());
    var checkUserTask = CheckUser();
    //create this task directly so we can refer to it later to get the result
    list.Add(checkUserTask);
    //wait for all of them to complete
    Task.WaitAll(list.ToArray());

    //get the result from the CheckUser call
    if (checkUserTask.Result == true)
        this.MainPage = new Layout.BrowsePage();
    else
        this.MainPage = new LoginPage();
}
受保护的异步任务启动()
{
页面起始页=空;
//创建要同时运行的项的列表
列表=新列表();
list.Add(App.Database.Migrations());
var checkUserTask=CheckUser();
//直接创建此任务,以便我们以后可以参考它以获得结果
list.Add(checkUserTask);
//等待它们全部完成
Task.WaitAll(list.ToArray());
//从CheckUser调用中获取结果
if(checkUserTask.Result==true)
this.MainPage=newlayout.BrowsePage();
其他的
this.MainPage=新登录页面();
}

好吧,你可以把所有东西都放到应用程序构造器中,当你加载应用程序时,splashscreen只会显示更长的时间,但我实际上认为这是一个较差的解决方案

有一个Splashscreen,然后是一个加载页面,看起来和Splashscreen完全一样,但是有一个进度条,或者加载图标,告诉用户它在做什么,这是一个更好的方法

如果您必须在用户看到第一页之前执行此操作,那么加载屏幕是一个很好的选项,可以让用户知道为什么要花这么长时间

我要添加的另一件事是存储已经加载的数据库的布尔值或版本号,因此您不需要运行迁移代码,除非您的应用程序版本增加


通过这样做,您可以在应用程序构造函数中放置此布尔检查,并立即加载第一页。如果需要迁移,请加载加载页面,让OnStart完成迁移,然后加载第一个应用程序屏幕。

您希望“更好的方法”是什么?为什么你会考虑显示一个加载页面是一个劣质的用户体验?我想如果应用程序需要5-8秒来加载,那么加载页面就可以了。它向用户显示正在进行的操作(正在进行迁移,…)。我测量了时间,启动应用程序(三星Galaxy A5)需要7秒。OP会在需要时更新数据库,然后从中检索用户信息。两者不能同时运行,一个依赖于另一个。