c# - 使用 async/await 和 Task.Run 时不显示特定异常

标签 c# io async-await task

我有一个包含食谱列表的网页。在我的代码中,我循环浏览页面并下载每个食谱。这是我正在做的伪代码:

//This is the Recipe class
//The constructor accepts a link to the recipe
//This method scrapes the recipe
public Task ScrapeAsync(){
    return Task.Run(async () => {
        string WebPage;
        WebRequest request = WebRequest.Create(link);
        request.Method = "GET";
        using (WebResponse response = await request.GetResponseAsync())
        using (StreamReader reader = new StreamReader(response.GetResponseStream())) {
            WebPage = await reader.ReadToEndAsync();
        }
        //Non - async code here which is used to scrape the webpage
    }
}

我使用 Task.Run 是因为方法中同时包含异步代码和阻塞代码。

//This is the RecipePage class
//This method scrapes the page
public Task GetRecipeListAsync(){
    return Task.Run(async () => {
        //I get the page using WebRequest and WebResponse in the same way as above

        //Non - async/blocking code here which scrapes the page and finds links to recipes. I do await Recipe.ScrapeAsync() somewhere here.
        //And I add the recipe objects to a public list in this class
    }
}

在表单中,它循环遍历页面列表并执行 await RecipePage.GetRecipeList() 和其他操作。
这是 for 循环所在的位置:

private async void go_Click(object sender, EventArgs e){
    for (int i = (int)startingPageNUD.Value; i <= (int)finishingPageNUD.Value; ++i) {
        RecipePage page = new RecipePage(page + i);
        await page.GetRecipeListAsync();
        //Some other code here
    }
}

我的问题是,每当 ScrapeAsync 方法发生异常时,Visual Studio 2013 都会指向 Application.Run(new Form1())

static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

并告诉我 Reflection.TargetInvocationException 已经发生。它没有显示我的代码中的实际异常。例如,如果我在代码中得到一个 NullReferenceException,它不会显示。 因此,我不得不同时编写异步和非异步代码,并使用非异步代码进行调试。有什么办法可以解决吗?
我还有一个问题。我是否以正确的方式使用 async/await 和 Task?

最佳答案

Am I using async/await and Task in the correct way?

非常接近。我认为在这种情况下不需要 Task.Run(它应该只用于将 CPU 密集型操作移出 UI 线程,并且 HTML 抓取通常足够快以留在 UI 上没有任何不良影响)。

我要提出的另一个建议是让 async Task 方法尽可能返回 值,而不是修改成员变量作为副作用。在您的情况下,考虑让 ScrapeAsync 返回其自己的列表而不是更新共享列表,并让调用代码执行列表合并。

关于您的异常,TargetInvocationException 将有一个包含详细信息的 InnerExceptionasync void 事件处理程序中的异常实际上与常规 void 事件处理程序中的异常管理方式相同:如果一个事件处理程序转义,那么它会进入应用程序主循环.如果您不想要它,则必须捕获它(对于同步和异步处理程序)。

关于c# - 使用 async/await 和 Task.Run 时不显示特定异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31340712/

相关文章:

java - 为什么 getClass().getResource 对 RandomAccessFile/ReversedLinesFileReader (Apache Commons) 有问题?

c - 用C写shell,如何区分交互模式和批处理模式

c# - 取消不接受 CancellationToken 的异步操作的正确方法是什么?

c# - Xamarin HttpClient.PostAsync 任务在 Android 中超时,在 iOS 中有效

azure - 持久函数 - 事件函数内的可等待任务

c# - 如何使用 HTML 敏捷包抓取内容

c# - 在单例中播种 Random() 的最佳方法

c# - session 中的引用对象

c# - 如何每天在同一时间在 C# 服务中执行一次代码?

java - Java 在文件中间写入的最佳方式