C# 异步任务方法后触发回调
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19003594/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Fire callback after async Task method
提问by jskidd3
I need to fire a callback when the foreach
loop has finished searching through each item int the List<>
.
我需要在foreach
循环完成搜索每个项目时触发回调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());
}
}
}
}
}
Is this possible and if so how can it be done?
这是可能的,如果可以,怎么做?
采纳答案by Sriram Sakthivel
It is very simple, just pass a method as a delegate in parameter. then invoke it wherever you need.
很简单,只需在参数中传递一个方法作为委托即可。然后在任何需要的地方调用它。
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.
}
回答by Kendall Frey
Since you're using await
, your code in startSearchBtn_Click
won't continue until Search
is finished.
由于您正在使用await
,您的代码在完成startSearchBtn_Click
之前不会继续Search
。
All you need is something like this:
你所需要的只是这样的:
private async void startSearchBtn_Click(object sender, EventArgs e)
{
await Search(files, selectTxcDirectory.SelectedPath, status);
// run your callback here
}
回答by noseratio
I'd code it like below. This way, you still keep track of the pending task (_pendingSearch
), while startSearchBtn_Click
remains synchronous.
我会像下面这样编码。这样,您仍然可以跟踪挂起的任务 ( _pendingSearch
),同时startSearchBtn_Click
保持同步。
You should be keeping track of pending tasks (and be able to cancel them). Otherwise, user may click startSearchBtn
twice in a row and spawn two search tasks. This still may be a valid scenario in your case, but usually it is not.
您应该跟踪挂起的任务(并能够取消它们)。否则,用户可能会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)
{
// ...
}
[EDITED]Using await
:
[编辑]使用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
}