|
//要执行的业务是从阿里云上下载将近40000条的音频到本地,单条下载忒慢,就想采用多线程,分配了二十个线程同时下载,省了很大部分的时间
class Program
{
static void Main(string[] args) {
string sql = "select en_audio,us_audio from t_audio LIMIT 198 ";
MySqlDataReader mySqlDataReader = DBHelper.ExecuteReader(sql);
List<String> sList = new 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)
{
while (mySqlDataReader.Read())
{
sList.Add(mySqlDataReader.GetString(0));
sList.Add(mySqlDataReader.GetString(1));
}
}
Console.WriteLine(sList.Count);
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
ThreadStart(sList);
WaitHandle.WaitAll(waits); //监听wait里面的所有的线程都已经set了 才执行下面的代码,否则一直在这里等待
stopwatch.Stop();
Console.WriteLine($"耗时{stopwatch.ElapsedMilliseconds}毫秒");
Console.ReadKey();
}
static Thread[] threads = new Thread[20];
static WaitHandle[] waits = new WaitHandle[20];
public static void ThreadStart(List<String> nums) {
//分配线程
for (int i=0;i<20;i++) {
threads[i] = new Thread(DownLoadFile);
waits[i] = new AutoResetEvent(false);
}
//为每个线程分配要执行的数据并开始执行
for (int i = 0; i < 20; i++)
{
if (i== threads.Length-1) {
var retult = nums.Skip(nums.Count / 20 * i).Take(nums.Count- nums.Count / 20*i).ToList();
threads[i].Start(new Objpt()
{
sList = retult,
WaitHandle = waits[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 as Objpt);
var sList = optObj.sList;
Console.WriteLine($"线程{optObj.ThreadIndex}开始了");
foreach (var url in sList)
{
try
{
count++;
var arrs = url.Split('/');
WebRequest request = WebRequest.Create(url);
HttpWebResponse res = (HttpWebResponse)request.GetResponse();
WebResponse response = request.GetResponse();
if (res.StatusCode.ToString() == "OK")
{
Stream responseStream = response.GetResponseStream();
using (FileStream fsWrite = new FileStream($"F:/Audio/v4/{arrs[arrs.Length - 2]}/{arrs[arrs.Length - 1]}", FileMode.OpenOrCreate, FileAccess.Write))
{
byte[] buffer = new byte[response.ContentLength];
while (true)
{
////返回本次实际读取到的字节数
int r = responseStream.Read(buffer, 0, buffer.Length);
if (r == 0)
{
break;
}
fsWrite.Write(buffer, 0, r);///写入
}
}
}
//if (count % 20 == 0 || count == sList.Count)
//{
// Console.WriteLine($"线程{optObj.ThreadIndex}已处理个数:{count}");
//}
}
catch (Exception ex)
{
string strErrorLogFile = System.AppDomain.CurrentDomain.BaseDirectory + $"\\{optObj.ThreadIndex}ErrorLog.log";
if (!System.IO.File.Exists(strErrorLogFile))
System.IO.File.WriteAllText(strErrorLogFile, "//系统错误日志记录文件\r\n");
object objSql ="线程"+ optObj.ThreadIndex.ToString()+ ex.Message;
System.IO.File.AppendAllText(strErrorLogFile, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\t" + objSql.ToString() + url + "\r\n");
}
}
Console.WriteLine($"线程{optObj.ThreadIndex}结束");
(optObj.WaitHandle as AutoResetEvent).Set(); //set方法是当某个线程结束起做个标记的作用
}
}
public class Objpt {
public List<String> sList { get; set; }
public WaitHandle WaitHandle { get; set; }
public int ThreadIndex { get; set; }
}
|
上一篇:net/c# 如何实现dns劫持下一篇:DateTime的使用
|