2014-09-26 1 views
0

Я хочу создать многопотоковый асинхронный менеджер загрузок. Но у меня проблемы с многопотоком. Один поток правильно работает, но когда я создаю вторую нить - ничего не работает. Я предполагаю, что проблема с синхронизацией webrequest. Я прочитал этот ответ Multithreading a large number of web requests in c#, но я не понял полностью. Теперь вопрос: как я могу изменить код для использования многопоточности (Thread, Threadpool).многопоточная программа с webrequests C#

класс DownloadableContent:

{ 
    private string url { get; set; } 
    private string path { get; set; } 
    private Stream streamResponse { get; set; } 
    private Stream streamLocal { get; set; } 
    private HttpWebRequest webRequest { get; set; } 
    private HttpWebResponse webResponse { get; set; } 

    public DownloadableContent(string url, string path) 
    { 
     this.url = url; 
     this.path = path; 
    } 

    public void Download() 
    { 
     using (WebClient wcDownload = new WebClient()) 
     { 
      try 
      { 
       webRequest = (HttpWebRequest)WebRequest.Create(url);     
       webRequest.Credentials = CredentialCache.DefaultCredentials; 
       webResponse = (HttpWebResponse)webRequest.GetResponse(); 
       Int64 fileSize = webResponse.ContentLength; 
       streamResponse = wcDownload.OpenRead(url); 
       streamLocal = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None); 
       byte[] downBuffer = new byte[2048];  
       int bytesSize = 0; 
       while ((bytesSize = streamResponse.Read(downBuffer, 0, downBuffer.Length)) > 0) 
       { 
        streamLocal.Write(downBuffer, 0, bytesSize); 
       } 
      } 
      finally 
      { 
       streamResponse.Close(); 
       streamLocal.Close(); 
      } 
     } 
    }  
} 

И класс main:

DownloadableContent file = new DownloadableContent("url", @"path"); 
Thread thread = new Thread(file.Download); 
thread.Start(); 
+0

Ваш код очень запутан. Вы используете 'WebClient' * и *' HttpWebRequest'. В результате вы делаете два запроса для каждого URL-адреса. Вы должны удалить 'webRequest' и' webResponse' и просто использовать 'WebClient'. –

+0

Скорее всего, причина, по которой вы столкнулись с проблемой, заключается в том, что вы не используете объекты 'webRequest' и' webResponse', которые вы создаете. По опыту я знаю, что это часто заставляет вещи перестать работать после нескольких запросов. Поскольку вы не используете их, просто удалите их из своего кода. –

+0

Я оставил в коде только «Webclient», и теперь он работает хорошо –

ответ

0

Стоит вам прочитать Async программирования затем взгляните на этот http://msdn.microsoft.com/en-us/library/System.Net.WebClient_methods(v=vs.110).aspx Вы имеете метод, чтобы загрузить вещь асинхронно. Также смотрите на TPL и избежать темы http://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx

Возможно чтение немного больше поможет вам избежать многих головных болей.

Это простой пример

private static void Main(string[] args) 
{ 
    var urlsAndPaths = new Dictionary<string, string>(); 
    urlsAndPaths.Add("http://i.forbesimg.com/media/lists/people/lionel-messi_416x416.jpg","messi.jpg"); 
    urlsAndPaths.Add("http://sizzlingsuperstars.com/wp-content/uploads/2014/07/Cristiano-Ronaldo-2-480x309.jpg", "cristiano.jpg");    
    foreach (var kvp in urlsAndPaths) 
    { 
     var wc = new WebClient(); 
     wc.DownloadFileAsync(new Uri(kvp.Key),kvp.Value); 
    } 
    Console.ReadKey(); 
} 
+0

спасибо за ответ, выглядит правильно, но условие программы - «Новая загрузка в новой теме» (задача обучения) с помощью Thread и Threadpool. (две разные реализации) –

+0

Я думаю, кому-то нужно обновить свои учебные материалы :) –

+0

Это задачи для новичков.NET :) –

0

В зависимости от версии платформы .NET, которую вы используете, вы можете воспользоваться классом задач. Вы могли бы сделать что-то вроде этого

foreach (var uri in myCollection) 
    { 
     Task.Factory.StartNew(() => 
     { 
      try 
      { 
       using (System.Net.WebClient client = new System.Net.WebClient()) 
       { 
        client.DownloadFileCompleted += (o, args) => 
        { 
         //Do something with the download 
        }; 
        client.DownloadFileAsync(uri); 

       } 
      } 
      catch (Exception ex) 
      { 
       //Do something 
      } 
     }); 
    } 
1

Лучший совет, который я могу вам дать, - использовать TPL. Это одна хорошая библиотека от Microsoft для управления потоками. Я использовал это для подобных проблем в своем коде, в основном мне приходилось загружать 8000 URL-адресов, в начале нормальный процесс занимал 30 минут. После того, как я использовал эту библиотеку, тот же процесс был завершен через 30 секунд.

TPL LINK

Task Parallel Library (TPL)

Пожалуйста, взглянуть на пример:

BookStore- GitHub

0

вы на .NET 4.5? «Новый способ» для этого - с Task.WhenAll, который загружает ваши асинхронные и параллельные загрузки, но позволяет фреймворку решить, следует ли/планировать работу в пуле потоков.

var client = new System.Net.WebClient(); 
await Task.WhenAll(urls.Select(url => { 
    var path = ?? // build local path based on url? 
    return client.DownloadFileAsync(url, path); 
}); 
+0

thx для ответа, но я использую .NET 4.0 –

 Смежные вопросы

  • Нет связанных вопросов^_^