2013-09-25 25 views
9

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()); 
       } 
      } 
     } 
    } 
} 

どうすればいいですか?

+2

パラメータとしてデリゲートを渡し、あなたに必要な 'foreach'ループでそれを起動しないのはなぜ?何か不足していますか? –

+0

http://msdn.microsoft.com/it-it/library/system.asynccallback.aspx – Saturnix

+0

@SriramSakthivel @SriramSakthivel @SriramSakthivelあなたは何も欠けていません。なぜなら、デリゲートをparamとして渡してforeachループは8-です)答えとして投稿してください。 – jskidd3

答えて

16

非常に単純ですが、パラメータ内のデリゲートとしてメソッドを渡すだけです。必要な場所で呼び出すことができます。

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. 
} 
1

あなたがawaitを使用しているのでSearchが終了するまで、startSearchBtn_Clickでコードは続行されません。

private async void startSearchBtn_Click(object sender, EventArgs e) 
{ 
    await Search(files, selectTxcDirectory.SelectedPath, status); 
    // run your callback here 
} 
2

私はそれが以下のようにコーディングしたい:

必要なのは、このようなものです。この方法では、まだ保留中のタスク(_pendingSearch)を追跡していますが、startSearchBtn_Clickは同期したままです。

保留中のタスクを追跡しておく必要があります(また、タスクをキャンセルすることもできます)。そうでない場合は、startSearchBtnを2回続けてクリックし、2つの検索タスクを開始することができます。これはあなたのケースではまだ有効なシナリオかもしれませんが、通常そうではありません。

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を使用して[EDITED]

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 
} 
+0

これは 'await'を使うよりもどのように優れていますか? – svick

+1

@svick、私のポイントは、ユーザーがこのボタンを何回かクリックしたときに、忘れないでください。私の個人的な好みは、火災や忘れを避けるために特に「非同期void」イベントハンドラを持たないことです。それにもかかわらず、 'async void'メソッドの中で保留中のタスクを追跡することは可能です。私はそれを示すためにコードを更新しました。 – Noseratio

+1

2つのコードを除いて、何か違うことをします。 'ContinueWith()'サンプルでは、​​ '_pendingSearch'は継続を表します。 'await'サンプルでは' Search() 'の' Task'です。 – svick

関連する問題