16

foreach当循环完成对 int 中的每个项目的搜索后,我需要触发回调List<>

private async void startSearchBtn_Click(object sender, EventArgs e)
{
    await Search(files, selectTxcDirectory.SelectedPath, status);
}

private static async Task Search(List<string> files, string path, Label statusText)
{
    foreach (string file in files)
    {
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load(file);

        statusText.Text = "Started scanning...";
        using (XmlReader reader = XmlReader.Create(new StringReader(xmlDoc.InnerXml), new XmlReaderSettings() { Async = true }))
        {
            while (await reader.ReadAsync())
            {
                if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "LineName"))
                {
                    Console.WriteLine(reader.ReadInnerXml());
                }
            }
        }
    }
}

这可能吗?如果可以,怎么做?

4

3 回答 3

23

很简单,只需在参数中传递一个方法作为委托。然后在需要的地方调用它。

private async void startSearchBtn_Click(object sender, EventArgs e)
{
    await Search(files, selectTxcDirectory.SelectedPath, status, SearchCompleted); // <-- pass the callback method here
}

private static async Task Search(List<string> files, string path, Label statusText, Action<string> callback)
{
    foreach (string file in files)
    {
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load(file);

        statusText.Text = "Started scanning...";
        using (XmlReader reader = XmlReader.Create(new StringReader(xmlDoc.InnerXml), new XmlReaderSettings() { Async = true }))
        {
            while (await reader.ReadAsync())
            {
                if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "LineName"))
                {
                    Console.WriteLine(reader.ReadInnerXml());
                }
            }
        }

        // Here you're done with the file so invoke the callback that's it.
        callback(file); // pass which file is finished
    }
}

private static void SearchCompleted(string file)
{
    // This method will be called whenever a file is processed.
}
于 2013-09-25T11:37:20.503 回答
4

我会像下面这样编码。这样,您仍然可以跟踪待处理的任务 ( _pendingSearch),同时startSearchBtn_Click保持同步。

您应该跟踪待处理的任务(并能够取消它们)。否则,用户可能会startSearchBtn连续单击两次并产生两个搜索任务。在您的情况下,这仍然可能是一个有效的场景,但通常不是。

Task _pendingSearch = null;
private void startSearchBtn_Click(object sender, EventArgs e)
{
    // check if is _pendingSearch != null and still pending here

    _pendingSearch = Search(files, 
        selectTxcDirectory.SelectedPath, status).ContinueWith((finishedTask) => 
    {
        // Place your completion callback code here
    }, TaskScheduler.FromCurrentSynchronizationContext);
}

private static async Task Search(List<string> files, string path, Label statusText)
{
    // ...
}

[编辑]使用await

Task _pendingSearch = null;
private async void startSearchBtn_Click(object sender, EventArgs e)
{
    // check if is _pendingSearch != null and still pending here

    _pendingSearch = Search(files, selectTxcDirectory.SelectedPath, status);
    await _pendingSearch;
    // Place your completion callback code here
}
于 2013-09-25T12:21:48.367 回答
2

由于您正在使用await,因此您的代码在完成startSearchBtn_Click之前不会继续Search

所有你需要的是这样的:

private async void startSearchBtn_Click(object sender, EventArgs e)
{
    await Search(files, selectTxcDirectory.SelectedPath, status);
    // run your callback here
}
于 2013-09-25T11:55:52.620 回答