首页 > 解决方案 > 在后台线程上运行数据下载

问题描述

我正在构建一个新应用程序,因为我希望它像每个人一样流畅,所以我想使用一个后台线程来负责使用 restsharp 下载所有数据。我也遵循 MVVM 模式。我已经阅读了很多关于 task.run 以及如何正确使用它以及整个 async-await 主题的内容。但由于我对这一切都是陌生的,我不确定我应该如何正确地做事。我有很多代码,所以我会简短地尝试解释我在做什么,然后放一个片段。

所以我开始创建一个服务类,其中包含所有使用 restsharp 获取数据的函数。在我的 ViewModel 中,我一开始就调用了这些函数。我尝试使用任务并在后台线程上运行这些功能,但应用程序在初始屏幕上被阻止。显然那是因为我做错了......所以我决定问你们。

例如,我有这个功能:

public string GetResPor()
{
    var restClient = new RestClient { BaseUrl = new Uri("http://xxx.xxx.xxx.xxx:xxxx") };
    var request = new RestRequest
    {
        Resource = "getCliPor",
        Method = Method.GET
    };
    request.AddParameter(new Parameter { Name = "idt", Value = GetImAsync().GetAwaiter().GetResult(), Type = ParameterType.GetOrPost });
    var result = restClient.Execute(request);
    Port = result.Content;
    return Port;
}

当我在 Task 上转换它时:

public async Task<string> GetResPor()
{
    var restClient = new RestClient { BaseUrl = new Uri("http://xxx.xxx.xxx.xxx:xxxx") };
    var request = new RestRequest
    {
        Resource = "getCliPor",
        Method = Method.GET
    };
    request.AddParameter(new Parameter { Name = "idt", Value = GetImAsync().GetAwaiter().GetResult(), Type = ParameterType.GetOrPost });
    var result = await restClient.ExecuteTaskAsync(request);
    Port = result.Content;
    return Port;
}

在 ViewModel 上,我首先创建我的服务类的新实例,然后:

Port = RD.GetRestauPort().GetAwaiter().GetResult();

这就是应用程序被阻止的地方,没有例外。

标签: apimvvmxamarin.formsasync-awaittask

解决方案


为了简单起见,让我们从基础开始。为了在后台线程中运行某些东西,最简单的方法是在Task.Run(). 这是做什么的:

将指定的工作排入队列以在 ThreadPool 上运行并返回该工作的任务或Task<TResult>句柄。

基本上,您将工作委托给 TreadPool,它会为您处理所有事情 - 寻找工作人员,等待工作人员完成其工作(在新线程上),然后通知您结果。

所以,基本上,无论你想在后台线程中做什么,简单的解决方案都是将它包装在 a 中Task.Run()并等待它的结果,以防你需要它。

另外,避免使用GetAwaiter().GetResult(). 异步编程中的简单规则是 - 如果可以等待,则一直等待

您可以阅读有关主题的更多信息

  1. 这个 SO 帖子
  2. 使用带有 Async/Await 的 Task.Run 的高级技巧
  3. 将 Task.Run 与 Async/Await 结合使用

推荐阅读