好的,情况如下:我的主要/ UI线程(称之为Thread1)用于从phsycial文档扫描程序中获取一批图像.获取批次后,会启动一个单独的“后台”线程(称为Thread2)来处理并保存该批次中的图像.
Thread2(“后台”线程)使用Parallel.For循环,与正常For循环相比,可将图像处理/保存时间缩短70%.但是,它似乎也是最大化我的所有处理器,因此Thread1无法开始获取任何更多的图像,直到Parallel.For循环完成.
有没有办法“限制”一个Parallel.For循环,以便它不会最大化我的处理器?或者设置处理优先级?我尝试设置Thread2.Priority = ThreadPriority.Lowest,但这似乎不会影响循环.或者我误解了Parallel.For循环是如何工作的?是以某种方式阻止Thread1?
public void SaveWithSettings(bool save) // method in Thread1 { .... Thread thr = new Thread(ThreadWork); // creating new thread (Thread 2) thr.Priority = ThreadPriority.Lowest; // does nothing? thr.Start(new SaveContainer(sc)); // pass a copy as paramater // misc stuff to make scanning possible again numBgw++; twain.RemoveAllImages(); // clear images imagelist.Clear(); // clear imagelist images .... // etc. this all appears to process fine while Thread2 is processing }
这是我的ThreadWork方法:
private void ThreadWork(object data) // executing in Thread2 { SaveContainer sc = data as SaveContainer; // holds images bool[] blankIndex = new bool[sc.imagelist.Count]; // to use in Parallel.For loop for (int i = 0; i < sc.imagelist.Count; i++) blankIndex[i] = false; // set default value to false (not blank) Parallel.For(0,sc.imagelist.Count,i => // loop to mark blank images { bool x = false; // local vars make loop more efficient x = sc.IsBlankImage((short)i); // check if image at index i is blank blankIndex[i] = x; // set if image is blank } .... // other image processing steps }
解决方法
public static void PriorityParallelForeach<T>(this IEnumerable<T> source,Action<T> action,ThreadPriority threadPriority,int? maxDegreeOfParallelism = null) { if (maxDegreeOfParallelism == null || maxDegreeOfParallelism<1) { maxDegreeOfParallelism = Environment.ProcessorCount; } var blockingQueue = new BlockingCollection<T>(new ConcurrentQueue<T>(source)); blockingQueue.CompleteAdding(); var tasks = new List<Task>() ; for (int i = 0; i < maxDegreeOfParallelism; i++) { tasks.Add(Task.Factory.StartNew(() => { while (!blockingQueue.IsCompleted) { T item; try { item = blockingQueue.Take(); } catch (InvalidOperationException) { // collection was already empty break; } action(item); } },CancellationToken.None,TaskCreationOptions.None,new PriorityScheduler(threadPriority))); } Task.WaitAll(tasks.ToArray()); }
要不就:
Parallel.ForEach(testList,item => { var privIoUsePrio = Thread.CurrentThread.Priority; // Set your desired priority Thread.CurrentThread.Priority = ThreadPriority.Lowest; TestCalc(item); //Reset privIoUse priority of the TPL Thread Thread.CurrentThread.Priority = privIoUsePrio; });