C#运行解析网站的多个任务,并在完成后返回

问题描述 投票:-1回答:1

我的目标是同时加载多个链接并为每个链接创建一个任务。

该任务将调用异步方法,该方法将解析链接并返回子链接,这些子链接将被解析(使用WebBrowser)然后它们返回下载链接。

第一个异步方法将调用2个后续方法来完成该工作。

我的问题是Task.Factory.ContinueWhenAll只会在所有第一个方法完成时返回,并且不会等待其余的工作完成。我只想继续准备所有下载链接,这可能需要多个网页解析才能实现。

目前我的代码如下:

var tasks = new List<Task>();
for (var index = 0; index < items_checklist.CheckedItems.Count; index++)
{
    var item = items_checklist.CheckedItems[index];
    Task task = Task.Factory.StartNew(
                    () => GetMirrors(((Item) item).Value, ((Item) item).Text)
                    , CancellationToken.None
                    , TaskCreationOptions.None
                    , TaskScheduler.FromCurrentSynchronizationContext()
    );
    tasks.Add(task);
 }

Task.Factory.ContinueWhenAll(tasks.ToArray(), GetLinks_Finished =>
{
    SetLinksButtonText(@"Links Ready");
    SetLinksButtonState(false);
    SetDownloadButtonState(true);
    Cursor.Current = DefaultCursor;
});

这将在所有GetMirrors完成时返回,但GetMirrors将调用“tempbrowser_DocumentCompleted”(WebBrowser完成事件),而后者将调用“LoadLinkIntoQueue”将下载链接加载到队列中。

我希望在执行所有LoadLinkIntoQueue时继续ContinueWhenAll。

我缺少什么逻辑?

c# async-await task multitasking
1个回答
2
投票

您可以在TaskCompletionSource方法中创建一个GetMirrors,这是在你的for循环网址中的Task.Factory.StartNew调用中使用的方法。

GetMirrors中,您将连接新WebBrowser的DocumentCompleted事件,该事件将调用TaskCompletionSource上的SetResult,使任务转换为Completed。

你的实现将是这样的:

Task<string> GetMirrors(string url, string somethingelse )
{

    // this will signal that the Task is completed
    // we want the parent to wait
    var tcs = new TaskCompletionSource<string>(TaskCreationOptions.AttachedToParent);

    // give each task their own WebBrowser instance
    WebBrowser tempbrowser = new WebBrowser();
    tempbrowser.ScriptErrorsSuppressed = true;
    this.Controls.Add(tempbrowser);

    tempbrowser.DocumentCompleted += (s, e) => {
        // LoadLinkIntoQueue call 
        // we have a result so signal to the CompletionSource that we're done
        tcs.SetResult(e.Url.ToString());

        this.Controls.Remove(tempbrowser);
    };

    // hook up errorhandling if you need that, left as an exercise.

    tempbrowser.Navigate(url);
    // we return the Task from the completion source
    return tcs.Task ; 
}

如果要返回发生的异常,还可以在TaskCompletionSource实例上调用SetException。

请注意,在此代码中,我为每个任务实例化Web浏览器,因此您不必担心将任务序列化为只有一个WebBrowser控件处理任务。

© www.soinside.com 2019 - 2024. All rights reserved.