2017-01-14 8 views
-1

Я пытаюсь создать класс, который может искать строку в списке сайтов асинхронным способом.Async & Tasks - Поиск по списку сайтов

Следующий код работает, но я получаю ощущение, что это делается совершенно неправильно:

public static class Searcher 
    { 

     public struct SearchResult 
     { 
      public SearchResult(string Url, bool Found) 
      { 
       this.Url = Url; 
       this.Found = Found; 
      }    

      public string Url; 
      public bool Found; 
     } 

     public async static Task<SearchResult> SearchWebsiteAsync(string url, string str) 
     { 
      HttpClient client = new HttpClient(); 
      var urlContents = await client.GetStringAsync(url); 

      System.Console.WriteLine("Found string in website {0}", url); 
      bool foundString = (urlContents.Contains(str) ? true : false); 

      return new SearchResult(url, foundString); 
     } 

     public static async Task<IEnumerable<SearchResult>> StartSearch(string str) 
     { 
      List<SearchResult> results = new List<SearchResult>(); 
      List<Task<SearchResult>> taskList = new List<Task<SearchResult>>(); 

      foreach (var url in TheWeb.URLs) 
      { 
       System.Console.WriteLine("Searching URL {0}", url); 

       var t = new Task<Task<SearchResult>>(() => SearchWebsiteAsync(url, str)); 
       t.Start(); 
       taskList.Add(t.Result); 
      } 
      //Task.WaitAll(tasks.ToArray()); 

      foreach (var task in taskList) { 
       results.Add(task.Result); 
      }    

      return results; 
     } 
    } 

Тем более, что у меня есть Task 'S внутри Task-х: var t = new Task<Task<SearchResult>>(() => SearchWebsiteAsync(url, str));

Есть Есть лучший способ (если возможно, без Parallel, потому что я все еще пытаюсь понять некоторое ожидание асинхронных ожиданий и задач)

+0

Если код работает, то это больше подходит для сайта [обзор кода] (https://codereview.stackexchange.com/), что делает этот вопрос непонятным. – Nkosi

+1

'HttpClient' предназначены для повторного использования и относительно долговечны; не создавайте новый для каждого запроса. – sellotape

ответ

2

Из того, что я понимаю в вашем коде, на самом деле это не так вопрос, к какому задаче приходят результаты поиска (так как url содержится в ваших результатах поиска в любом случае).

Так как насчет

public static async Task<SearchResult[]> StartSearch(string str) 
{ 
    List<Task<SearchResult>> taskList = new List<Task<SearchResult>>(); 

    foreach (var url in TheWeb.URLs) 
    { 
     System.Console.WriteLine("Searching URL {0}", url); 
     taskList.Add(SearchWebsiteAsync(url, str)); 
    } 

    return await Task.WhenAll<SearchResult>(taskList); 
} 

async функции возвращают Task объекты. Для их инициализации вам не нужно new Task(() => {...}). Просто вызвать функцию async достаточно, чтобы вернуть действительный объект Task.

Я предполагаю, что вы согласны с получением всех результатов поиска в одно и то же время. Если это допущение неверно, дайте мне знать. Возможны и другие решения.