【问题标题】:Using the Async framework to make a web call使用 Async 框架进行网络调用
【发布时间】:2012-08-17 05:26:09
【问题描述】:

我正在使用async 框架进行网络调用。我在下面的代码中发现了一个错误

class Program
{
    static void Main(string[] args)
    {
        TestAsync async = new TestAsync();
        await async.Go();//Error:  the await operator can only be used with an async method.  Consider markign this method with the async modifier.  Consider applying the await operator to the result of the call
    }
}

class TestAsync
{
    public async Task Go()
    {
        using (WebClient client = new WebClient())
        {
            var myString =  await client.DownloadStringTaskAsync("http://msdn.microsoft.com");
            Console.WriteLine(myString);
        }    
    }
}

我已经尝试了此代码的几种变体。它要么在运行时失败,要么无法编译。在这种情况下,该方法在我的异步调用被允许触发之前完成。我做错了什么?

我的目标是以异步方式使用 WebClient 执行对网站的调用。我想将结果作为字符串返回并使用Console.WriteLine 打印出来。如果您觉得从执行的代码开始更舒服,只需更改

await async.Go();async.Go(); 代码会运行,但不会命中 Console.WriteLine。

【问题讨论】:

  • Main() 中直接使用 await 没有任何意义。你希望它做什么?
  • 我想异步执行网络调用。该函数是任意的,我只想设置一个基本的异步调用来学习语法的基础知识。随意以任何您认为合适的方式拨打网络电话。
  • 在 .net 中学习异步的好资源:msdn.microsoft.com/en-us/vstudio/hh378091
  • 顺便说一句,using 对于WebClient 是不必要的。大多数时候,你应该确保你 Dispose() 任何实现 IDisposable 的东西,但 WebClient 拥有它只是因为它的基础 (Component) 有。

标签: c# visual-studio-2012 c#-5.0


【解决方案1】:

程序在网络请求完成之前就结束了。这是因为 Main 不会等待异步操作完成,因为它无事可做。

我敢打赌,如果你让 Main 持续更长时间,那么 Console.WriteLine 会被跟注。

我会尝试在调用异步方法后添加睡眠 - Thread.Sleep(500) - 任何足够长的时间以允许网络请求完成都应该有效。

【讨论】:

  • 一个合理的答案。但是,我期待异步框架提供阻塞机制。等待对我来说听起来像是一个障碍......
  • 如果有时需要更长的时间怎么办?下载一些文件可能需要几个小时,这是否意味着我也必须等待几个小时才能下载一些小文件?如果下载失败并抛出异常会怎样?
  • 同意,thread.sleep 是一种糟糕的线程同步方式。对我的代码来说还不错,因为它被扔掉了。
  • 我只提供这个答案来解释为什么他没有看到Console.WriteLine,并提供一个简单的解决方案。我绝不认为应该使用Thread.Sleep 来同步线程,但它完全可以帮助您学习新的异步功能,而无需像Wait() 那样强制一个完整的块。
【解决方案2】:

错误消息正确地告诉您await 只能在async 方法中使用。但是,你不能让Main()async,C# 不支持。

但是 async 方法返回 Tasks,与自 .Net 4.0 以来 TPL 中使用的 Task 相同。而Tasks 确实支持使用the Wait() method 进行同步等待。所以,你可以这样写你的代码:

class Program
{
    static void Main(string[] args)
    {
        TestAsync async = new TestAsync();
        async.Go().Wait();
    }
}

在这里使用Wait() 是正确的解决方案,但在其他情况下,混合使用Wait() 的同步等待和使用await 的异步等待可能很危险并且可能导致死锁(尤其是在GUI 应用程序或ASP.NET 中) )。

【讨论】:

  • 我明白了,所以我使用的是控制台应用程序这一事实使这成为一个古怪的小测试。仅供参考,Task 是在 .net 4 中引入的。
猜你喜欢
  • 2015-03-16
  • 1970-01-01
  • 2020-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多