这个方法是利用PDF控件将每页转成Image列表返回,本来是没用到Task线程操作的,
但是pdf.ConvertPageToPNGMemoryStream()这个方法每页转换耗时将近1秒,
页数少还好说,页数多了就会卡界面,所以想用线程提高速度,
然后遇到这个奇怪的现象,假设PDF只有1页,单步调试中会报错,
注释下面这句的 i = 2 ???就很奇怪明明循环只跑1次就结束了啊,
求助大神能否帮忙解答一下,或者这个方法正确的优化写法是怎样的,
多谢多谢
private List<Image> PDFToImageList(Pdf.Document pdf)
{
List<Image> lst = new List<Image>();
Task[] tasks = new Task[pdf.Pages.Count];
for (int i = 1; i <= pdf.Pages.Count; i++)
{
Image img = new Image();
tasks[i - 1] = Task.Factory.StartNew(() =>
{
System.Windows.Media.Imaging.BitmapImage bitmapImage = new System.Windows.Media.Imaging.BitmapImage();
//调试报异常越界,i=2?
using (MemoryStream stream = pdf.ConvertPageToPNGMemoryStream(pdf.Pages[i]))
{
stream.Position = 0;
bitmapImage.BeginInit();
bitmapImage.CacheOption = System.Windows.Media.Imaging.BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = stream;
bitmapImage.DecodePixelWidth = (int)(this.noticeWidth * 1.3);
bitmapImage.EndInit();
bitmapImage.Freeze();
container.Dispatcher.Invoke(() =>
{
img.Source = bitmapImage;
lst.Add(img);
});
}
});
}
Task.WaitAll(tasks);
return lst;
}
有点像js的闭包问题,task是异步执行的,但是匿名函数中引用到了i,task没执行for就已经执行完毕了,这样执行线程的时候i已经是for循环后的值2越界了。
怕界面假死,用一个线程来处理就行了吧,干嘛用多线程,多线程的话看你代码也会有bug,线程的执行完毕先后不一定是完全按照for中的先后,所以也会出现转为图片顺序和pdf不一致
改成下面的单线程
private List<Image> PDFToImageList(Pdf.Document pdf)
{
List<Image> lst = new List<Image>();
var task = Task.Factory.StartNew(() =>
{
for (int i = 1; i <= pdf.Pages.Count; i++)
{
Image img = new Image();
System.Windows.Media.Imaging.BitmapImage bitmapImage = new System.Windows.Media.Imaging.BitmapImage();
//调试报异常越界,i=2?
using (MemoryStream stream = pdf.ConvertPageToPNGMemoryStream(pdf.Pages[i]))
{
stream.Position = 0;
bitmapImage.BeginInit();
bitmapImage.CacheOption = System.Windows.Media.Imaging.BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = stream;
bitmapImage.DecodePixelWidth = (int)(this.noticeWidth * 1.3);
bitmapImage.EndInit();
bitmapImage.Freeze();
container.Dispatcher.Invoke(() =>
{
img.Source = bitmapImage;
lst.Add(img);
});
}
}
});
Task.WaitAll(task);
return lst;
}
一定要多线程可以用下面的,将i当做参数传入
private List<Image> PDFToImageList(Pdf.Document pdf)
{
List<Image> lst = new List<Image>();
Task[] tasks = new Task[pdf.Pages.Count];
for (int i = 1; i <= pdf.Pages.Count; i++)
{
tasks[i - 1] = Task.Factory.StartNew((objI) =>
{
int index = (int)objI;
lst[index] = new Image();//使用下标来定位,防止生成顺序错误,而且放到task里面,而不是外面Image img=new Image然后引用img对象,这样没有越界,但是只有最后页面有图片,什么原因和i的问题一样
System.Windows.Media.Imaging.BitmapImage bitmapImage = new System.Windows.Media.Imaging.BitmapImage();
//调试报异常越界,i=2?
using (MemoryStream stream = pdf.ConvertPageToPNGMemoryStream(pdf.Pages[index]))
{
stream.Position = 0;
bitmapImage.BeginInit();
bitmapImage.CacheOption = System.Windows.Media.Imaging.BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = stream;
bitmapImage.DecodePixelWidth = (int)(this.noticeWidth * 1.3);
bitmapImage.EndInit();
bitmapImage.Freeze();
container.Dispatcher.Invoke(() =>
{
lst[index].Source = bitmapImage;//使用下标来定位,防止生成错落
});
}
}, i);
}
Task.WaitAll(tasks);
return lst;
}
您好,我是有问必答小助手,您的问题已经有小伙伴解答了,您看下是否解决,可以追评进行沟通哦~
如果有您比较满意的答案 / 帮您提供解决思路的答案,可以点击【采纳】按钮,给回答的小伙伴一些鼓励哦~~
ps:问答VIP仅需29元,即可享受5次/月 有问必答服务,了解详情>>>https://vip.csdn.net/askvip?utm_source=1146287632