Задача — скачать почти 40 000 аудиофрагментов из Alibaba Cloud в локальную зону, и одна загрузка очень медленная, поэтому я хочу использовать многопоточность и выделить 20 потоков для скачивания одновременно, что позволит сэкономить много времени Программа класса {
static void Main(string[] args) { строка sql = "выбрать en_audio,us_audio из t_audio LIMIT 198"; MySqlDataReader mySqlDataReader = DBHelper.ExecuteReader(sql); List<String> sList = новый List<String>(); sList.Add("https://qutifen-qudao.oss-cn-beijing.aliyuncs.com/mfg/audio/v3/1abacus_en.ogg"); sList.Add("https://qutifen-qudao.oss-cn-beijing.aliyuncs.com/mfg/audio/v3/2abacus_en.ogg"); if (mySqlDataReader.HasRows) { в то время как (mySqlDataReader.Read()) { sList.Add(mySqlDataReader.GetString(0)); sList.Add(mySqlDataReader.GetString(1)); } } Console.WriteLine(sList.Count); Секундомер = новый секундомер (); секундомер. Start(); ThreadStart(sList); WaitHandle.WaitAll(waits); Все потоки в ожидании прослушивания настроены перед выполнением следующего кода, иначе они будут ждать здесь секундомер. Стоп(); Console.WriteLine($"Time-heming{секундомер. ElapsedMilliseconds}milliseconds»); Console.ReadKey();
} статические резьбы[] резьбы = новые резьбы[20]; статический WaitHandle[] waits = новый WaitHandle[20]; public static void ThreadStart(List<String> nums) { Назначение потоков для (int i=0; I<20; i++) { потоки[i] = новый поток(DownLoadFile); waits[i] = новый AutoResetEvent(false);
} Назначайте данные каждому потоку для выполнения и запуска для (int i = 0; Мне < 20; i++) { если (i== потоки. Длина-1) { VAR Retult = Nums. Skip(nums. Count / 20 * i). Take(nums. Считай-числа. Count / 20*i). ToList(); threads[i]. Старт(новый Objpt() { sList = retult, WaitHandle = ожидание[i], ThreadIndex = i }); } else { VAR Retult= Nums. Skip(nums. Count / 20 * i). Take(nums. Count / 20). ToList(); threads[i]. Start(new Objpt() { sList = retult, WaitHandle=waits[i], ThreadIndex=i }); }
} }
public static void DownLoadFile(Object obj) { int count = 0; Objpt optObj = (obj как Objpt); var sList = optObj.sList; Console.WriteLine($"Thread{optObj.ThreadIndex} started"; foreach (ссылка var в sList) { Попробуй { count++; var arrs = url. Split('/'); WebRequest request = WebRequest.Create(url); HttpWebResponse res = (HttpWebResponse)запрос. GetResponse(); WebResponse response = запрос. GetResponse(); если (рез. StatusCode.ToString() == «OK») { Ответ потокаStream = ответ. GetResponseStream(); using (FileStream fsWrite = новый FileStream($"F:/Audio/v4/{arrs[arrs[arrs. Длина - 2]}/{arrs[arrs. Длина - 1]}", FileMode.OpenOrCreate, FileAccess.Write)) { byte[] buffer = новый байт[ответ. ContentLength]; Пока (правда) { Возвращает количество фактически прочитанных байтов на этот раз int r = responseStream.Read(buffer, 0, buffer. Длина); если (r == 0) { перерыв; } fsWrite.Write(buffer, 0, r); Писать
} } } если (count % 20 == 0 || count == sList.Count) //{ Console.WriteLine($"Thread{optObj.ThreadIndex} processed:{count}"); //}
} catch (исключение, например) { строка strErrorLogFile = System.AppDomain.CurrentDomain.BaseDirectory + $"\\{optObj.ThreadIndex}ErrorLog.log"; если (! System.IO.File.Exists(strErrorLogFile)) System.IO.File.WriteAllText (strErrorLogFile, "//System ErrorLog File\r\n"); object objSql = «thread» + optObj.ThreadIndex.ToString() + ex. Сообщение; System.IO.File.AppendAllText(strErrorLogFile, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\t" + objSql.ToString() + url + "\r\n");
}
} Console.WriteLine($"Thread{optObj.ThreadIndex} ends"); (optObj.WaitHandle как AutoResetEvent). Set(); Метод множества — отмечать, когда поток заканчивается } }
публичный класс Objpt { public<String> List sList { get; декорация; } public WaitHandle WaitHandle { get; декорация; } public int ThreadIndex { get; декорация; }
}
|