多线程执行效率
判断线程执行完成胡方法
(1)CountdownEvent
(2)AutoResetEvent
默认情况下,程序运行时共享所有的处理器,也可指定特定的CPU运行
Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1);
1.线程池 ThreadPool
ThreadPool 类 (System.Threading) | Microsoft Docs
线程池可用于执行任务、发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。
线程池使用后台线程,如果所有前台线程均已终止,则不会使应用程序保持运行。
使用线程池,可以通过向应用程序提供由系统管理的工作线程池,来更有效地使用线程。
调用 QueueUserWorkItem 方法以将方法排队以便在线程池线程上执行。 在工作项排队后,无法取消该工作项。
每个线程都使用默认堆栈大小,并按默认优先级运行。
for (int k=0;k< readImgPath.Count;k++)
{
ThreadPool.QueueUserWorkItem(SaveImage, readImgPath[k]);
}
public static void SaveImage(Object obj)
{
ImgStruct s = (ImgStruct)obj;
File.Copy(s.imgPath, saveFolder + "\\"+Thread.CurrentThread.ManagedThreadId+"_" + s.imgName);
count.Signal();
}
测试时间:590.05ms
2.Task类
Task 类 (System.Threading.Tasks) | Microsoft Docs
表示不返回值并且通常以异步方式执行的单个操作。默认情况下,任务计划在线程池线程上运行。
Task t = Task.Factory.StartNew(()=>{
for(int k=0;k< readImgPath.Count;k++)
{
SaveImage(readImgPath[k]);
}
});
t.Wait();
测试时间:5933.27ms
同步运行
Task[] tasks = new Task[readImgPath.Count];
for (int k = 0; k < tasks.Length; k++)
{
var m = k;
tasks[k] = new Task(() =>
{
SaveImage(readImgPath[k]);
});
tasks[k].RunSynchronously();
}
测试时间:5933.27ms
3.并行任务 Parallel
Parallel 类 (System.Threading.Tasks) | Microsoft Docs
支持并行循环
//类似迭代器访问数据
Parallel.ForEach<ImgStruct>(readImgPath, s =>
{
File.Copy(s.imgPath, saveFolder + "\\" + Task.CurrentId + "-" + s.imgName);
count.Signal();
});
测试时间:1783.38ms
//索引号访问数据
Parallel.For(0, readImgPath.Count, i => //
{
File.Copy(readImgPath[i].imgPath, saveFolder + "\\" + Task.CurrentId + "$$-" + readImgPath[i].imgName);
count.Signal();
});
测试时间:3185.67ms
//方法并行
for(int k=0;k< readImgPath.Count;k++)
{
Parallel.Invoke(() => {
{
File.Copy(readImgPath[k].imgPath, saveFolder + "\\" + Task.CurrentId + "$$-" + readImgPath[k].imgName);
count.Signal();
}});
}
测试时间:3980.97ms
4.更新UI线程 BackgroundWorder
BackgroundWorker 类 (System.ComponentModel) | Microsoft Docs
在单独的线程上执行操作。
BackgroundWorker work = new BackgroundWorker();
work.WorkerReportsProgress = true;
work.WorkerSupportsCancellation = true;
work.DoWork += new DoWorkEventHandler(SaveImage2);
work.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(Work_RunWorkerCompleted);
//work.ProgressChanged
if (work.IsBusy)
Console.WriteLine("Work Busy!");
else
work.RunWorkerAsync();
public static void SaveImage2(Object o,DoWorkEventArgs e)
{
if (readImgPath.Count > 0)
{
sw.Start();
foreach (ImgStruct s in readImgPath)
{
if(work.CancellationPending)
{
e.Cancel = true;
return;
}
else
{
File.Copy(s.imgPath, saveFolder + "\\BACKWORK_" + s.imgName);
count.Signal();
}
}
}
}
private static void Work_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if(e.Error!=null)
{
return;
}
if(!e.Cancelled)
{
Console.WriteLine("Run Worker Finished \n");
}
}
测试时间:5984.08ms