2014-12-25 2 views
0

Я загружаю строку с веб-страницы с помощью System.Net.WebClient.DownloadStringTaskAsync асинхронно.Отмена DownloadStringTaskAsync и его перезапуск

Примерно 4 из 5 раз, это завершается успешно, но иногда это зависает, и мне придется перезапустить программу, чтобы «перезагрузить» ее.

Таким образом, я имею в виду реализации тайм-аут, который автоматически отменяет задачу через 5 секунд и перезапускает его:

async void DoTasks() 
{ 
    string output; 

    int timeout = 5000; 
    WebClient client = new WebClient() { Encoding = Encoding.UTF8 }; 
    Task<string> task = client.DownloadStringTaskAsync(url); 
    if (await Task.WhenAny(task, Task.Delay(timeout)) == task) 
    { 
     output = task.Result; 
    } 
    else 
    { 
     client.CancelAsync(); 
     DoTasks(); 
    } 
} 

Это, однако, возвращает NullReferenceException.

+0

Невозможно, чтобы этот код мог вызвать «NullReferenceException». Вероятно, это внутри метода GetTasks. Кроме того, вы не используете «WebClient». –

+0

Вам нужно добавить метод 'GetTasks' к вопросу. –

+0

Извините, GetTasks должен был быть DoTasks - перезапуск метода – jacobz

ответ

-1

Я не эксперт в ожидании/асинк, я все еще учился, но, может быть, вы должны сделать что-то подобное?

using System; 
using System.Net; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine("Inline code to test"); 
      Console.WriteLine(StartTask(true)); 

      Console.WriteLine("Get actual website to test, write the length of the text only"); 
      Console.WriteLine(StartTask(false).Length); 

      Console.Write("Press any key"); 
      Console.ReadKey(); 
     } 

     static string StartTask(bool DoTestInsteadOfGetUrl) 
     { 
      var task = DoTasks(DoTestInsteadOfGetUrl); 
      Task.WaitAny(task); 

      return task.Result; 
     } 

     async static Task<string> DoTasks(bool DoTestInsteadOfGetUrl) 
     { 
      int timeout = 20; 
      int count = 1; 
      CancellationTokenSource cts; 
      string output;     
      do 
      { 
       cts = new CancellationTokenSource(timeout); 
       if (DoTestInsteadOfGetUrl) 
       { 
        output = await Task<string>.Run(() => test(count, cts.Token), cts.Token); 
       } 
       else 
       { 
        WebClient client = new WebClient() { Encoding = Encoding.UTF8 }; 
        output = await Task<string>.Run(() => client.DownloadStringTaskAsync("http://www.google.com"), cts.Token); 
       } 

       if (cts.IsCancellationRequested) 
       { 
        Console.WriteLine("try #" + count++); 
        timeout += DoTestInsteadOfGetUrl ? 100 : 50; 
       } 
      } while (cts.IsCancellationRequested); 

      return output; 
     } 

     async static Task<string> test(int count, CancellationToken ct) 
     { 
      int sleep = 400 - (count * 5); 
      await Task.Run(() => Task.Delay(sleep), ct); 

      if (!ct.IsCancellationRequested) 
      { 
       Console.WriteLine("succeed #" + count); 
      } 
      return sleep.ToString(); 
     } 
    } 
} 
+0

С этим кодом многое не так. Во-первых, он не включает вызов «WebClient» OP, который вам нужно сделать внутри 'DoTasks'. Но ваши 'DoTasks' являются' void' и не содержат модификатора 'async'. В настоящее время это не решит проблему OP. –

+0

@YuvalItzchakov, я обновил свой код ... надеюсь, что это лучше – Fredou