C#Windows Universal应用程序未检测到异步方法

时间:2016-06-12 07:50:07

标签: c# windows asynchronous

所以我正在尝试编写一个简单的通用应用程序来从网上获取比特币的价格。我有一个异步方法,我从here获取从网址获取json并将其放入一个字符串。这是我调用方法的地方:

        public App()
        {
            this.InitializeComponent();
            this.Suspending += OnSuspending;

            CoinPriceBackend CP = new CoinPriceBackend();

            string response = await GetFromAPI();
        }

这是方法:

        async Task<string> GetFromAPI()
        {
            try
            {
                //Create HttpClient
                HttpClient httpClient = new HttpClient();

                //Define Http Headers
                httpClient.DefaultRequestHeaders.Accept.TryParseAdd("application/json");

                //Call
                string ResponseString = await httpClient.GetStringAsync(
                    new Uri("https://api.bitcoinaverage.com/ticker/GBP/"));
                //Replace current URL with your URL

                return ResponseString;
            }

            catch (Exception ex)
            {
                return "ERROR: " + ex;
            }
        }

我收到错误

'The 'await' operator can only be used within an async method. 
Consider marking this method with the 'async' modifier and changing its return type to 'Task'.'

但方法 async ...我该如何解决这个问题?

谢谢!

3 个答案:

答案 0 :(得分:1)

  

方法是 async

仔细查看错误消息;它不是在谈论GetFromAPI - 它在谈论App

但是,正如其他人所指出的,构造函数不能标记为async

  

我正在尝试编写一个简单的通用应用

通用Windows应用程序 - 与所有其他现代平台一样 - 无法阻止基于I / O的操作的UI线程。用户体验太糟糕了,大多数应用程序商店都会测试自动拒绝执行此操作的应用程序。

换句话说:App在应用程序启动时被调用(大概)。当用户启动您的应用时,它必须快速启动 并显示 ASAP 。等待下载完成根本不是一种选择。

因此,要真的修复此问题,您需要启动下载(而不是等待它完成)并将您的应用程序初始化为&#34; loading& #34;州 - 显示微调器或&#34;装载......&#34;消息或其他什么。然后,下载完成后,更新您的应用以显示您需要的内容。

我在async constructors上有一篇博客文章和关于async MVVM的文章系列(如果你正在做MVVM),但是一个非常基本的方法看起来像这样:

public Task Initialization { get; }
public string Value { get; private set { /* code to raise PropertyChanged */ } }

public App()
{
  this.InitializeComponent();
  this.Suspending += OnSuspending;

  CoinPriceBackend CP = new CoinPriceBackend();

  Value = "Loading..."; // Initialize to loading state.
  Initialization = InitializeAsync();
}

private async Task InitializeAsync()
{
  try
  {
    string response = await GetFromAPI();
    ...
    Value = response; // Update data-bound value.
  }
  catch (Exception ex)
  {
    ... // Display to user or something...
  }
}

答案 1 :(得分:0)

在函数中使用await时,应将函数定义为async

但是对于App()构造函数,你将无法做到这一点。您可以定义另一个函数,您可以从中调用返回string的函数。

喜欢这个

public App()
{
    CallApi();
}

private async void CallApi()
{
    response = await GetFromAPI();
}

答案 2 :(得分:0)

C#不允许将构造函数标记为异步。

您有三个主要选择:

1)重构在异步事件处理程序中调用此方法;

2)使用Task.Run生成一个新线程并在那里运行异步代码。这可能导致将编组结果返回到UI线程并将值分配给某些UI元素的问题;

3)使其同步(阻塞)呼叫。这可能是最简单的选择。

您必须进行以下更改。

   string response = GetFromAPI().Result;

请注意,这可能会导致死锁,因为Task会尝试在主线程中重新开始,主线程已经通过调用'.Result'锁定,因此您需要进行另一次更改。此外,没有意义

Task<string> GetFromAPI()
{
    ....

    return httpClient.GetStringAsync(new Uri("https://api.bitcoinaverage.com/ticker/GBP/")).ConfigureAwait(false);

    ...
}