C# 卡在异步方法上

C# 卡在异步方法上,c#,multithreading,async-await,C#,Multithreading,Async Await,可能有一些明显的错误,但我正在做一些没有经验的事情。我正试图从互联网上获取一个字符串,但它不起作用。在WinRT中,我们必须在异步方法中使用HttpClient,我的做法如下:- private async void update() { try { rawdata = await client.GetStringAsync(url); } catch

可能有一些明显的错误,但我正在做一些没有经验的事情。我正试图从互联网上获取一个字符串,但它不起作用。在WinRT中,我们必须在异步方法中使用HttpClient,我的做法如下:-

    private async void update()
    {
        try
        {   
                rawdata = await client.GetStringAsync(url);     

        }
        catch
        {
            rawdata = "Updation failed. Error code:vish42042";
        }

      }
下面是代码的调用方式:-

    string temp = @url;
                update();
          WAIT:
                if (rawdata == null) {
                    goto WAIT;
                }
rawdata是一个全局变量,我在goto WAIT上做了如下检查:查看代码到底在哪里失败,以及它在这里的失败。我希望当从互联网上更新rawdata时,if循环会中断,但它从未发生过。我做得不对吗?显然我没有用我所知道的最好的方式做,但这也是错的吗?。问题在哪里


更新:事实上,问题不在于如何使这个功能工作,它是一个或两个修改工作。真正的问题是如何确保在调用update函数后更新rawdata,因为此后的代码希望它不是null而是更新的

经过一些很好的解释和回答,我认为这就是问题可以解决的地方:-

     string xmlstring = xmlupobj.getUpdatedData(); 
     // Above is the ultimate point of return of data. 
    //Next code line is this, which throws a null exception 
                    XDocument xmldoc = XDocument.Parse(xmlstring);
所以我认为在使GetUpdateData异步后,返回Task,如果我们可以将Task转换为适当的字符串(如果它已下载),如果它未下载,则转换为null,那么我们可以使用一些错误的代码行进行检查,如下所示:-

    string xmlstring = xmlupobj.getUpdatedData();
    WAIT:
        if (xmlstring == null)
        {
            goto WAIT;
        }
        xmldoc = XDocument.Parse(xmlstring);

因此,如果它是正确的,唯一剩下的问题是如何设置xmlstring?

您应该让此方法返回一个任务:

那么当你叫它:

string temp = @url;
await update();

// rawdata will be set here
另一个选项是直接返回字符串,而不是在变量中设置:

private async Task<string> UpdateAsync()
{
    try
    {
        using (var client = new HttpClient())
        {
            return await client.GetStringAsync(url);     
        }
    }
    catch
    {
        return "Updation failed. Error code:vish42042";
    }
}  

请注意,这两种方法都要求调用方也是异步方法。

您应该使此方法返回任务:

那么当你叫它:

string temp = @url;
await update();

// rawdata will be set here
另一个选项是直接返回字符串,而不是在变量中设置:

private async Task<string> UpdateAsync()
{
    try
    {
        using (var client = new HttpClient())
        {
            return await client.GetStringAsync(url);     
        }
    }
    catch
    {
        return "Updation failed. Error code:vish42042";
    }
}  
请注意,这两种方法都要求调用方也是异步方法。

根据您的更新:


事实上,问题不在于如何使这个函数工作,而是需要进行一两次修改。真正的问题是如何确保在调用update函数后更新rawdata,因为此后的代码希望它不是null而是更新的

答案很简单。你不能

使该方法异步的全部目的是调用update不会设置正确的值,它会启动一些工作单元,将其设置在将来的某个未知点,同时让您继续执行程序而不是等待。为了确保在update返回之前设置变量,您需要使方法同步,并在方法内部等待值的存在,而不是使用异步

如果希望保持update Asychrous,则需要进行一些简单的修改,如中所示,以便在计算结果时通知调用方,然后可以等待该方法,或者使用ContinueWith手动添加一个continuation,计算结果后执行所需代码。

基于您的更新:


事实上,问题不在于如何使这个函数工作,而是需要进行一两次修改。真正的问题是如何确保在调用update函数后更新rawdata,因为此后的代码希望它不是null而是更新的

答案很简单。你不能

使该方法异步的全部目的是调用update不会设置正确的值,它会启动一些工作单元,将其设置在将来的某个未知点,同时让您继续执行程序而不是等待。为了确保在update返回之前设置变量,您需要使方法同步,并在方法内部等待值的存在,而不是使用异步


如果希望保持update Asychrous,则需要进行一些简单的修改,如中所示,以便在计算结果时通知调用方,然后可以等待该方法,或者使用ContinueWith手动添加一个continuation,在计算结果后执行所需的代码。

更好的做法是,将其更改为返回任务,而不是修改全局变量。我尝试了它。很抱歉,它给出了一个错误,即等待关键字只能在异步方法中使用。因此,我必须使该方法也异步???@vish213是的-你需要一个异步方法,实际上问题不在于如何使该函数工作,真正的问题是如何确保调用update函数后更新rawdata,也就是说,之后的代码期望它不是null而是nullupdated@vish213对这就是创建异步概念的原因。您不仅使一个低级方法异步,还使链上的所有方法都异步。这是不可避免的。更好的是,将其更改为返回任务,而不是修改全局变量

可以。我试过了。很抱歉,但它给出了一个错误,等待关键字只能在异步方法中使用。因此,我必须使该方法也异步???@vish213是的-你需要一个异步方法,实际上问题不在于如何使该函数工作,真正的问题是如何确保调用update函数后更新rawdata,也就是说,之后的代码期望它不是null而是nullupdated@vish213对这就是创建异步概念的原因。您不仅使一个低级方法异步,还使链上的所有方法都异步。这是不可避免的。@TorrentalCodeing我不知道为什么你的编辑建议被拒绝了,它显然是有效的。我希望您不介意我以我的名义进行编辑。@hvd没问题,恢复编辑是正确的做法,无论编辑的作者是谁:即使你可以做你想做的事情,等待更新完成,你的应用程序也会阻止主线程并导致认证失败。要编辑,你仍在尝试进行忙碌的等待,在等待过程中循环,而变量未设置。不要那样做。这是一个可怕的资源密集型系统,而事实上它甚至不起作用。您应该使用Reed向您展示的实现修改update以返回任务,然后在解析XML并对其执行任何操作后,修改调用者以返回一个或多个任务。@TorrentialCodeding我不知道您的编辑建议被拒绝的原因,它显然是有效的。我希望您不介意我以我的名义进行编辑。@hvd没问题,恢复编辑是正确的做法,无论编辑的作者是谁:即使你可以做你想做的事情,等待更新完成,你的应用程序也会阻止主线程并导致认证失败。要编辑,你仍在尝试进行忙碌的等待,在等待过程中循环,而变量未设置。不要那样做。这是一个可怕的资源密集型系统,而事实上它甚至不起作用。您应该使用Reed向您展示的实现修改update以返回任务,然后在解析XML并对其执行任何操作后,修改调用者以返回一个或多个任务。感谢您给出了清晰的答案。实际上,我开发了一个WPF应用程序,现在我正在将其转换为WinRT应用程序。我在WPF中的方法显然是同步的,但是由于WinRT中的限制,我们不能在同步方法中使用WebClient,所以我所要做的就是找到最好的替代方法。@vish213最好的替代方法是使您的代码“一路异步”,正如其他人已经提到的那样。谢谢您的明确回答。实际上,我开发了一个WPF应用程序,现在我正在将其转换为WinRT应用程序。我在WPF中的方法显然是同步的,但是由于WinRT中的限制,我们不能在同步方法中使用WebClient,所以我所要做的就是找到最好的替代方法。@vish213最好的替代方法是使您的代码“一路异步”,正如其他人已经提到的那样。