如何在同步方法中使用异步任务

时间:2019-07-17 05:33:29

标签: c# uwp

我有一个异步任务,该任务在一定的延迟后返回字符串。我在方法中使用了Async任务,以获取附加的字符串作为输出。

我使用了按钮和标签。我已经使用Button Click事件来加载名为“文本”的标签的文本。

我不想在按钮单击中使用延迟。

private void Load_Click(object sender, RoutedEventArgs e)
{
    text.Text = "";
    TextAsync();        
    text.Text = text.Text + newValue;
    text.Text =text.Text+ "Ashokkumar Viswanathan";
}

internal async Task<string> LoadText()
{
    await Task.Delay(20000);
    newValue = "Async Value";
    return newValue;
}

private async void TextAsync()
{
    await LoadText();
}

预期输出:text.Text="Async Value Ashokkumar Viswanathan

实际输出:text.Text="Ashokkumar Viswanathan"

4 个答案:

答案 0 :(得分:1)

  

如何在同步方法中使用异步任务

我认为您对自己的问题感到困惑,因为您尝试做错了事。您实际上想要阻止UI线程,这给您的客户带来了更糟糕的用户体验。另外,这是一个UWP应用程序,因此请注意,如果这是您的分发方式,则阻止UI会导致被应用程序商店拒绝。

如果您要解决的 actual 问题类似于“在操作完成之前不要让用户再次单击按钮”,那么适当的解决方案将与之匹配,例如,禁用按钮,直到操作完成。

但是,假设您确实想阻止UI线程并为您的用户提供有关软件的更糟糕的体验,则可以使用hacks described in this article之一。这些黑客都无法在每种情况下正常工作,因此我们无法知道它们是否对您有用,但是就您而言,我想线程池黑客将使您能够阻止UI线程而不会出现死锁:

private void Load_Click(object sender, RoutedEventArgs e)
{
  text.Text = "";
  Task.Run(() => LoadText()).GetAwaiter().GetResult();
  text.Text = text.Text + newValue;
  text.Text = text.Text+ "Ashokkumar Viswanathan";
}

最后一点,我必须强调,我不建议这样做。我认为没有理由故意降低用户体验。

答案 1 :(得分:0)

只需将事件处理程序更改为async void,并将await的结果更改为TextAsync

private async void Load_Click(object sender, RoutedEventArgs e)
{
      text.Text = "";
      var s =  await TextAsync();
      text.Text = text.Text + s + "Ashokkumar Viswanathan";
}

答案 2 :(得分:-1)

这是您代码的修改版本:

private async void Load_Click(object sender, RoutedEventArgs e)
{
    text.Text = "";
    var newValue = await TextAsync();
    text.Text = text.Text + newValue;
    text.Text = text.Text + "Ashokkumar Viswanathan";
}
internal async Task<string> LoadText()
{
    return await Task.FromResult("Async Value");
}

private async Task<string> TextAsync()
{
    return await LoadText();
}
  

这里做什么?

  1. 根据设计要求在各个位置固定Async-Await
  2. 对于LoadText(),请使用Task.FromResult作为硬编码值或任何异步传递字符串值的内容
  3. 事件必须异步,如果异步方法可以将void作为返回值以保持向后兼容性的原因,那么它们就是其中之一,因为在内部连接中,您无法使用await进行代码调用,因为没有{{1 }}返回

答案 3 :(得分:-2)

  

我不想将Button clicked事件设为异步。我想知道,是否可以在普通按钮单击中使用异步任务来获取文本。

不使用TextAsync,因为它不会返回Task(应有),但是如果直接调用LoadText(),则可以使用ContinueWith方法:< / p>

private void Load_Click(object sender, RoutedEventArgs e)
{
    text.Text = "";
    LoadText().ContinueWith(t =>
    {
        text.Text = text.Text + newValue;
        text.Text = text.Text + "Ashokkumar Viswanathan";
    }, System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}

我仍然建议您将事件处理程序定义为asyncawait的{​​{1}}和TextAsync()。这是推荐的方法:

LoadText()