等待直到任务完成才阻止 - c#

我试图用RequestHandler.ParseAll()阻止await ConsumerTask;,但是当我在其中设置断点时,我总是首先获得“ Done ...”输出...然后Parse2()失败,并显示NullReferenceException。 (这就是我的猜测:“由于_handler超出范围,GC开始清理”)

无论如何,我不知道为什么会这样。

class MainClass
{
    public async void DoWork()
    {
        RequestHandler _handler = new RequestHandler();
        string[] mUrls;
        /* fill mUrls here with values */
        await Task.Run(() => _handler.ParseSpecific(mUrls));
        Console.WriteLine("Done...");
    }
}
static class Parser
{
    public static async Task<IEnumerable<string>> QueryWebPage(string url) { /*Query the url*/ }

    public static async Task Parse1(Query query) 
    { 
        Parallel.ForEach(/*Process data here*/);
    }

    public static async Task Parse2(Query query)
    {
        foreach(string line in query.WebPage)
            /* Here i get a NullReference exception because query.WebPage == null */
    }
}
sealed class RequestHandler
{
    private BlockingCollection<Query> Queue;
    private Task ConsumerTask = Task.Run(() => /* call consume() for each elem in the queue*/);

    private async void Consume(Query obj)
    {
        await (obj.BoolField ? Parser.Parse1(obj) : Parser.Parse2(obj));
    }

    public async void ParseSpecific(string[] urls)
    {
        foreach(string v in urls)
            Queue.Add(new Query(await QueryWebPage(v), BoolField: false));

        Queue.CompleteAdding();
        await ConsumerTask;
        await ParseAll(true);
    }

    private async Task ParseAll(bool onlySome)
    {
        ReInit();
        Parallel.ForEach(mCollection, v => Queue.Add(new Query(url, BoolField:false)));
        Queue.CompleteAdding();
        await ConsumerTask;
        /* Process stuff further */
    }
}
struct Query
{
    public readonly string[] WebPage;
    public readonly bool BoolField;
    public Query(uint e, IEnumerable<string> page, bool b) : this()
    {
        Webpage = page.ToArray();
        BoolField = b;
    }
}

参考方案

CodesInChaos在注释中发现了问题。这是因为异步方法返回了void,而您几乎不应该这样做-这意味着您无法跟踪它们。

相反,如果您的异步方法没有要返回的实际值,则应使它们返回Task

发生的情况是,ParseSpecific仅在直到没有立即完成的第一个await QueryWebPage(v)同步运行。然后返回...所以任务从这里开始:

await Task.Run(() => _handler.ParseSpecific(mUrls));

...立即完成,并打印“完成”。

一旦使所有异步方法都返回Task,就可以等待它们。您也完全不需要Task.Run。因此,您将拥有:

public async void DoWork()
{
    RequestHandler _handler = new RequestHandler();
    string[] mUrls;
    await _handler.ParseSpecific(mUrls);
    Console.WriteLine("Done...");
}

...

public async TaskParseSpecific(string[] urls)
{
    foreach(string v in urls)
    {
        // Refactored for readability, although I'm not sure it really
        // makes sense now that it's clearer! Are you sure this is what
        // you want?
        var page = await QueryWebPage(v);
        Queue.Add(new Query(page, false);
    }

    Queue.CompleteAdding();
    await ConsumerTask;
    await ParseAll(true);
}

您的Reinit方法也需要更改,因为当前ConsumerTask基本上将立即完成,因为Consume将立即返回,因为这是另一个返回void的异步方法。

坦白说,您所拥有的内容看起来非常复杂,没有对async / await的正确理解。我会在async / await上阅读更多,然后可能从头开始。我强烈怀疑您可以简化很多事情。您可能还想阅读TPL Dataflow,它旨在简化生产者/消费者的情况。

多重处理:map与map_async - python

使用map和map_async有什么区别?将列表中的项目分配给4个进程后,它们是否运行相同的功能?因此,假设两者都在异步和并行运行是错误的吗?def f(x): return 2*x p=Pool(4) l=[1,2,3,4] out1=p.map(f,l) #vs out2=p.map_async(f,l) python大神给出的解决方案 将作业映射到流程…

如何从DOMXPath::query()方法获取完整的HTML? - php

我有要从中提取未删除内容的特定div的文档。我做:$dom = new DOMDocument(); $dom->loadHTML($string);//that's HTML of my document, string 和xpath查询:$xpath = new DOMXPath($dom); $xpath_resultset = $xp…

使用pandas dataframe.query()选择列 - python

dataframe.query()上的文档非常简洁http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.query.html。我也无法通过网络搜索找到投影的示例。因此,我尝试仅提供列名:这给出了语法错误。对于键入select,然后键入列名也是如此。那么..该怎么做? py…

等待异步方法中已完成的任务 - c#

当我们调用异步方法时,我们返回一个包装器任务。public async Task ExecuteActionAsync() { // no await called } public async Task ExecuteActionAwaitAsync() { // await called on a completed await Task.Complet…

string.split(“ _(B”) - java

基本上,这行代码行不通,我不确定原因: String[] stringHolder = string.split("_(B"); 我收到此错误:索引3附近的未封闭组此行代码有效: String[] stringHolder = string.split("_B"); 因此,这使我相信它是由“(”引起的。有人可以告诉我如…