简体   繁体   English

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

[英]C# Windows Universal app not detecting async method

So I'm trying to write a simple universal app to get the price of bitcoin from the web. 因此,我试图编写一个简单的通用应用程序,以从网络上获取比特币的价格。 I have an async method that I got from here to get the json from a url and put it into a string. 我有一个异步方法,是从这里获取的,用于从URL中获取json并将其放入字符串中。 Here is where I called the method: 这是我调用该方法的地方:

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

            CoinPriceBackend CP = new CoinPriceBackend();

            string response = await GetFromAPI();
        }

And this is the method: 这是方法:

        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;
            }
        }

I get the error 我得到错误

'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'.'

But the method is async... How can I fix this? 但是该方法异步的...我该如何解决?

Thanks! 谢谢!

But the method is async 但是方法异步的

Take a closer look at the error message; 仔细查看错误消息; it's not talking about GetFromAPI - it's talking about App . 这不是在谈论GetFromAPI ,而是在谈论App

However, as others have pointed out, constructors cannot be marked async . 但是,正如其他人指出的那样,构造函数不能标记为async

I'm trying to write a simple universal app 我正在尝试编写一个简单的通用应用程序

Universal Windows apps - like all other modern platforms - cannot block the UI thread for I/O-based operations. 像所有其他现代平台一样,通用Windows应用程序无法阻止UI线程进行基于I / O的操作。 The user experience is just too bad, and there are tests in most app stores to auto-reject apps that do this. 用户体验太糟糕了,大多数应用程序商店中都有测试可以自动拒绝执行此操作的应用程序。

Put another way: App is called (presumably) on application startup. 换句话说: App被调用(大概)在应用程序启动。 When the user launches your app, it has to start up quickly and show something ASAP . 当用户启动您的应用,它具有快速启动和展示一些东西尽快 Waiting for a download to complete is simply not an option. 根本无法等待下载完成。

So, to really fix this, you need to just start the download (not waiting for it to complete) and initialize your application to a "loading" state - showing a spinner or "Loading..." message or whatever. 因此,要真正解决此问题,您只需开始下载(不等待其完成)并将应用程序初始化为“正在加载”状态-显示微调器或“正在加载...”消息或其他内容。 Then, when the download completes, update your app to display what you need to. 然后,下载完成后, 更新您的应用以显示所需内容。

I have a blog post on async constructors and an article series on async MVVM (if you're doing MVVM), but a really basic approach could look something like this: 我有一篇关于async构造函数的博客文章,以及一篇关于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...
  }
}

When you use an await within a function you should define the function as async . 在函数中使用await ,应将函数定义为async

But for App() constructor you will be unable to do that. 但是对于App()构造函数,您将无法做到这一点。 You can defined another function from which you can call your function which return string . 您可以定义另一个函数,从中可以调用返回string的函数。

Like this 像这样

public App()
{
    CallApi();
}

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

C# does not allow constructors to be marked as async. C#不允许将构造方法标记为异步。

You have three main options: 您有三个主要选择:

1) refactor to call this method in async event handler; 1)重构以在异步事件处理程序中调用此方法;

2) spawn a new thread using Task.Run and run async code there. 2)使用Task.Run产生一个新线程,并在那里运行异步代码。 This could lead to issues of marshalling result back to UI thread and assigning value to some UI element; 这可能导致将结果编组回UI线程并为某些UI元素分配值的问题;

3) make it synchronous (blocking) call. 3)使其成为同步(阻塞)调用。 This probably is the easiest option. 这可能是最简单的选择。

You will have to make following changes. 您将必须进行以下更改。

   string response = GetFromAPI().Result;

Note that this will probably cause deadlock as Task will try to reaume in the main thread, which is already locked by call to '.Result', therefore you need another change. 请注意,这可能会导致死锁,因为Task将尝试在主线程中重新获得执行权限,该主线程已通过调用'.Result'进行锁定,因此您需要进行其他更改。 Also, there is no point 而且,没有意义

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

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

    ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM