【问题标题】:What is the right way to call a Task from MainPage从 MainPage 调用任务的正确方法是什么
【发布时间】:2019-11-14 11:12:22
【问题描述】:

如果 await 只能由 async 方法使用,我如何从 MainPage() 调用任务?

我的代码示例:

public MainPage()
{
    InitializeComponent();
    label.Text=await Task.Run(TaskTest); //this doesn't work
}

private async Task<string> TaskTest()
    {
        try
        {
            using (WebClient client = new WebClient())
            {
               return await client.DownloadStringTaskAsync("https://www.example.com/return.php");
//also tried w/ no success:
//return client.DownloadStringTaskAsync("https://www.example.com/return.php").Result;
            }
        }
        catch (Exception)
        {
            throw;
        }
    }

【问题讨论】:

  • 你没有。构造函数并不意味着创建异步流。你可能想看看this question
  • label.Text = await Task.Run 非常混乱。 UI 在单独的线程上运行。您可能希望为 await 任务分配一个值,然后将其分配给 label.Text。

标签: c# xamarin task


【解决方案1】:

避免使用async void 即发即弃的方法。

然而,事件处理程序是该规则的唯一例外。

参考Async/Await - Best Practices in Asynchronous Programming

在这种情况下,由于您想等待任务,然后创建有助于实现所需行为的事件和处理程序

public MainPage() {
    InitializeComponent();
    Downloading += OnDownloading; //subscribe to event
    Downloading(this, EventArgs.Empty); //raise event to be handled
}

private event EventHandler Downloading = delegate { };

private async void OnDownloading(object sender, EventArgs args) {
     //Downloading -= OnDownloading; //unsubscribe (optional)
    label.Text = await TaskTest(); //this works
}

private async Task<string> TaskTest() {
    try {
        using (WebClient client = new WebClient()) {
           return await client.DownloadStringTaskAsync("https://www.example.com/return.php");
        }
    } catch (Exception) {
        throw;
    }
}

【讨论】:

    【解决方案2】:

    您不能使Main() 方法异步,因此,您可以在Main() 函数的主体中使用await 关键字。

    您可以通过编辑当前代码实现的一个简单解决方法是让您的函数TaskTest() 返回void,这样您就不必等待它的调用。

    示例:

    public MainPage()
    {
        InitializeComponent();
        TaskTest();
    }
    private async void TaskTest()
    {
        try
        {
            using (WebClient client = new WebClient())
            {
               label.Text = await client.DownloadStringTaskAsync("https://www.example.com/return.php");
            }
        }
        catch (Exception)
        {
            throw;
        }
    }
    

    编辑

    如果您必须等待异步调用的返回值而不使用await,您可以继续使用一段时间来检查Task是否已完成。

    Task<string> accessTokenTask = Task.Run<string>(() => MethodToGetToken());
    // wait until operation is done.
    while(!accessTokenTask.IsCompleted)
    {
        accessTokenTask.Wait():
    }
    // once the task completes, the runtime will step out of the while loop
    // and you can access your Token in the Result
    
    string token = accessTokenTask.Result;
    

    希望这能回答你的问题。

    【讨论】:

    • 谢谢你,@machariadev!但如果我想等呢?例如,如果返回的字符串实际上是一个登录令牌,我必须等待它的响应才能显示一些数据或不显示。你能给我这个帮助吗?
    【解决方案3】:

    您可能不应该从MainPage 调用您的Task。我从 Visual Studio 空白页开始,并尝试做同样的事情。我找到了一个建议使用await Navigation.PushModalAsync(NewPage); 的答案,然后在那里调用任务Task.Run(async () =&gt; { await method(); }).Wait();。它有效,但not the best way to do it。

    这个article on CodeProject 非常适合帮助初学者在空白页项目中添加MVVM。您只需要将ViewModel 绑定到MainPage,然后从ViewModel 调用您的Task。

    public MainPage()
    {
       InitializeComponent();
       this.BindingContext = new MainPageViewModel(this);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-10
      • 1970-01-01
      • 1970-01-01
      • 2011-11-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多