2013-09-25 26 views
9

foreach döngüsü, List<> öğesinin her bir öğesiyle aramayı bitirdiğinde bir geri arama başlatmam gerekiyor.Anlaşmazlıktan sonra yangın geri arama Görev yöntemi

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

Bu mümkün mü ve eğer öyleyse nasıl yapılabilir?

+2

Neden parametre olarak bir temsilci geçirmek ve gereken yere foreach' döngü 'bunu çağırmak değil? Bir şey mi eksik? –

+0

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

+0

@SriramSakthivel Hiçbir şey kaçırmıyorsunuz, çünkü bir delegeyi bir geçit olarak geçirmenin ne olduğunu bilmiyorum. foreach loop 8-) Bunu bir cevap olarak gönderir misiniz? – jskidd3

cevap

16

Çok basit, parametre olarak temsilci olarak bir yöntemi iletmeniz yeterlidir. O zaman ihtiyacın olan her yerde onu çağır. Search tamamlanana kadar

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

Eğer await kullandığınız için, startSearchBtn_Click içinde kod devam etmeyecektir.

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

Ben aşağıda gibi kod ediyorum:

Tek ihtiyacınız böyle bir şeydir. Bu şekilde, hala bekleyen görevi (_pendingSearch) takip ederken, startSearchBtn_Click senkronize kalır.

Beklemedeki görevleri takip etmelisiniz (ve bunları iptal edebileceksiniz). Aksi halde, kullanıcı arka arkaya iki kez startSearchBtn'u tıklayabilir ve iki arama görevini yapabilir. Bu hala sizin durumunuzda geçerli bir senaryo olabilir, ancak genellikle değildir.

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) 
{ 
    // ... 
} 

[REDAKTE]await kullanma:

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

Bu 'bekle' kullanmaktan daha iyi nasıl olur? – svick

+1

@svick, benim amacım, kullanıcı bu düğmeyi birden çok kez tıklatabildiğinde, yangın-ve-unutma yaklaşımını kullanmamaktır. Kişisel tercihim, özellikle yangın ve unutmayı önlemek için "async void" olay işleyicilerine sahip olmamak. Yine de, 'async void' yönteminde bekleyen görevi takip etmek mümkündür, bunu göstermek için kodu güncelledim. – Noseratio

+1

İki kod parçası dışında farklı bir şey yapın. 'ContinueWith()' örneğinizde '_pendingSearch ', devam durumunu gösterir. 'Bekle' örneğinde, 'Ara() '' Görev' 'dir. – svick