问题描述
我试着并行使用。NET JPEG文件的大小调整。我所有的尝试失败了,因为Graphics.DrawImage-FUNC似乎锁定,而活跃。请尝试以下剪断:
I've tried to parallelize the resizing of jpegs using .Net. All my tries failed, because the Graphics.DrawImage-func seems to lock while active. Try the following snipped:
Sub Main()
Dim files As String() = IO.Directory.GetFiles("D:\TEMP")
Dim imgs(25) As Image
For i As Integer = 0 To 25
imgs(i) = Image.FromFile(files(i))
Next
Console.WriteLine("Ready to proceed ")
Console.ReadLine()
pRuns = 1
For i As Integer = 0 To 25
Threading.Interlocked.Increment(pRuns)
Threading.ThreadPool.QueueUserWorkItem(New Threading.WaitCallback(AddressOf LongTerm), imgs(i))
Next
Threading.Interlocked.Decrement(pRuns)
pSema.WaitOne()
Console.WriteLine("Fin")
Console.ReadLine()
End Sub
Sub LongTerm(ByVal state As Object)
Dim newImageHeight As Integer
Dim oldImage As Image = CType(state, Image)
Dim newImage As Image
Dim graph As Graphics
Dim rect As Rectangle
Dim stream As New IO.MemoryStream
Try
newImageHeight = Convert.ToInt32(850 * oldImage.Height / oldImage.Width)
newImage = New Bitmap(850, newImageHeight, oldImage.PixelFormat)
graph = Graphics.FromImage(newImage)
rect = New Rectangle(0, 0, 850, newImageHeight)
With graph
.CompositingQuality = Drawing2D.CompositingQuality.HighQuality
.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
End With
'Save image to memory stream
graph.DrawImage(oldImage, rect)
newImage.Save(stream, Imaging.ImageFormat.Jpeg)
Catch ex As Exception
Finally
If graph IsNot Nothing Then
graph.Dispose()
End If
If newImage IsNot Nothing Then
newImage.Dispose()
End If
oldImage.Dispose()
stream.Dispose()
Console.WriteLine("JobDone {0} {1}", pRuns, Threading.Thread.CurrentThread.ManagedThreadId)
Threading.Interlocked.Decrement(pRuns)
If pRuns = 0 Then
pSema.Set()
End If
End Try
End Sub
所有线程等待graph.DrawImage()。有没有一种方法使用其它功能,以加快code性能?它是不可能使用Graphics.Draw多线程?在实际应用中的多个图像应在同一时间(在四核件)被调整,并不总是一样。该贴code仅用于测试目的...
All threads wait at graph.DrawImage(). Is there a way to speed up code performance using other functions? Is it impossible to use Graphics.Draw with multiple threads? In the real application multiple images should be resized at the same time (on a quad-core pc), not always the same. The posted code is only for testing purposes...
在此先感谢
编辑:更新,并根据意见,code
Updated the code according to comments
推荐答案
GDI +模块每个进程了很多办法。是的,有疼痛感,但有没有办法解决它。幸运的是有像这样的(以及任何一个处理文件系统上的文件)的任务,这是太容易了,拆的工作量了多个进程之间。幸运的是,它看起来像的GDI使用锁,不互斥,所以它是并发!
Use Processes.
GDI+ blocks per process a lot of ways. Yep, a pain, but there's no way around it. Fortunately with tasks like this one (and any one that processes files on the filesystem), it's too easy to just split the workload up between multiple processes. Fortunately it looks like GDI+ is using locks, not mutex, so it is concurrent!
我们有一些图形程序,我的工作做的图像处理。一个程序员开始6-7份一次的转换程序,在生产中。因此,这不是乱了,相信我。哈克?你没有得到支付给看看pretty的。把工作做好!
We have some graphics programs where I work to do image processing. One programmer starts 6-7 copies at once of a conversion program, in production. So it is not messy, trust me. Hack? You're not getting paid to look pretty. Get the job done!
Imports System.Drawing
Module Module1
Dim CPUs As Integer = Environment.ProcessorCount
Dim pRuns As New System.Collections.Generic.List(Of Process)
Sub Main()
Dim ts As Date = Now
Try
If Environment.GetCommandLineArgs.Length > 1 Then
LongTerm(Environment.GetCommandLineArgs(1))
Exit Sub
End If
Dim i As Integer = 0
Dim files As String() = IO.Directory.GetFiles("D:\TEMP", "*.jpg")
Dim MAX As Integer = Math.Min(26, files.Count)
While pRuns.Count > 0 Or i < MAX
System.Threading.Thread.Sleep(100)
If pRuns.Count < CInt(CPUs * 1.5) And i < MAX Then ''// x2 = assume I/O has low CPU load
Console.WriteLine("Starting process pRuns.count = " & pRuns.Count & " for " & files(i) & " path " & _
Environment.GetCommandLineArgs(0))
Dim p As Process = Process.Start(Environment.GetCommandLineArgs(0), """" & files(i) & """")
pRuns.Add(p)
i += 1
End If
Dim i2 As Integer
i2 = 0
While i2 < pRuns.Count
If pRuns(i2).HasExited Then
pRuns.RemoveAt(i2)
End If
i2 += 1
End While
End While
Catch ex As Exception
Console.WriteLine("Blew up." & ex.ToString)
End Try
Console.WriteLine("Done, press enter. " & Now.Subtract(ts).TotalMilliseconds)
Console.ReadLine()
End Sub
Sub LongTerm(ByVal file As String)
Try
Dim newImageHeight As Integer
Dim oldImage As Image
Console.WriteLine("Reading " & CStr(file))
oldImage = Image.FromFile(CStr(file))
Dim rect As Rectangle
newImageHeight = Convert.ToInt32(850 * oldImage.Height / oldImage.Width)
Using newImage As New Bitmap(850, newImageHeight, oldImage.PixelFormat)
Using graph As Graphics = Graphics.FromImage(newImage)
rect = New Rectangle(0, 0, 850, newImageHeight)
With graph
.CompositingQuality = Drawing2D.CompositingQuality.HighQuality
.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
End With
Console.WriteLine("Converting " & CStr(file))
graph.DrawImage(oldImage, rect)
Console.WriteLine("Saving " & CStr(file))
newImage.Save("d:\temp\Resized\" & _
IO.Path.GetFileNameWithoutExtension(CStr(file)) & ".JPG", _
System.Drawing.Imaging.ImageFormat.Jpeg)
End Using
End Using
Catch ex As Exception
Console.WriteLine("Blew up on " & CStr(file) & vbCrLf & ex.ToString)
Console.WriteLine("Press enter")
Console.ReadLine()
End Try
End Sub
End Module
这篇关于并行化GDI +图像大小调整.NET的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!