Завдання — завантажити майже 40 000 аудіозаписів з Alibaba Cloud у локальну зону, і одне завантаження відбувається дуже повільно, тому я хочу використовувати багатопотокове завантаження і виділяти 20 потоків для завантаження одночасно, заощаджуючи багато часу Програма класу {
static void Main(string[] args) { String 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(чекає); Усі потоки очікування для прослуховування встановлені перед виконанням наступного коду, інакше вони чекатимуть тут секундомір. Stop(); Console.WriteLine($"Time-henting{секундомір. ElapsedMilliseconds}milliseconds»); Console.ReadKey();
} статична різьба[] різьба = нова різьба[20]; статичний WaitHandle[] чекає = новий WaitHandle[20]; public static void ThreadStart(List<String> nums) { Призначити потоки для (int i=0; i<20; i++) { threads[i] = новий Thread(DownLoadFile); waits[i] = новий AutoResetEvent(false);
} Призначте дані кожному потоку для виконання та початку виконання для (int i = 0; Мені < 20; i++) { якщо (i== потоки. Довжина-1) { VAR Retult = Nums. Skip(nums. Count / 20 * i). Візьміть(nums. Лічимо-число. Count / 20*i). ToList(); threads[i]. Start (новий Objpt() { sList = ретульт, WaitHandle = чекає[i], ThreadIndex = i }); } інше { VAR retult= Nums. Skip(nums. Count / 20 * i). Візьміть(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 url у sList) { спробуйте { count++; var arrs = url. Спліт('/'); WebRequest request = WebRequest.Create(url); HttpWebResponse res = (HttpWebResponse)запит. GetResponse(); WebResponse rep = запит. 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 = відповідьStream.Read(buffer, 0, buffer. Довжина); якщо (r == 0) { перерва; } fsWrite.Write(buffer, 0, r); Пиши
} } } якщо (кількість % 20 == 0 || count == sList.Count) //{ Console.WriteLine($"Thread{optObj.ThreadIndex} оброблений:{count}"); //}
} catch (виняток, наприклад) { string 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} закінчується"); (optObj.WaitHandle як AutoResetEvent). Set(); Метод множини полягає у позначенні, коли потік закінчується } }
публічний клас Objpt { public<String> List sList { get; декорація; } public WaitHandle WaitHandle { get; декорація; } public int ThreadIndex { get; декорація; }
}
|