VB.Net Background Worker代码报错:Object is currently in use elsewhere
解决思路及代码修正
问题根源
异常是因为后台线程在修改Destination Bitmap的同时,UI线程通过ProgressChanged事件绑定该Bitmap到PictureBox1.Image,两个线程同时访问同一个Bitmap资源,引发资源占用冲突。
具体解决方案
分离UI预览与后台处理的资源
不要在ProgressChanged中直接绑定正在修改的Destination,仅在该事件中更新进度文本,待后台处理完成后,再将最终的Destination赋值给PictureBox。优化图像操作性能(可选但推荐)
GetPixel和SetPixel是低效的像素操作方法,改用LockBits直接操作内存,既能提升处理速度,也能减少线程间资源竞争的概率。
修改后的代码示例
修正后台工作者与进度更新逻辑
Private Sub BGWProcess_DoWork(sender As Object, e As DoWorkEventArgs) Handles BGWProcess.DoWork For Y = 0 To hgt If BGWProcess.CancellationPending Then e.Cancel = True Exit Sub End If For X = 0 To wid Destination.SetPixel(X, Y, Source.GetPixel(X, Y)) Next BGWProcess.ReportProgress(Y) Next ' 处理完成后将Destination作为结果传递 e.Result = Destination End Sub Private Sub BGWProcess_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles BGWProcess.ProgressChanged ' 仅更新进度文本,不操作Bitmap TxtProgress.Text = e.ProgressPercentage.ToString End Sub Private Sub BGWProcess_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BGWProcess.RunWorkerCompleted If Not e.Cancelled AndAlso e.Error Is Nothing Then ' 处理完成后再绑定到PictureBox PictureBox1.Image = CType(e.Result, Bitmap) End If End Sub
用LockBits优化像素操作(推荐)
如果图像尺寸较大,替换GetPixel/SetPixel为LockBits能大幅提升效率,同时降低线程冲突风险:
Private Sub BGWProcess_DoWork(sender As Object, e As DoWorkEventArgs) Handles BGWProcess.DoWork ' 锁定Source和Destination的内存 Dim srcData = Source.LockBits(New Rectangle(0, 0, Source.Width, Source.Height), Imaging.ImageLockMode.ReadOnly, Source.PixelFormat) Dim destData = Destination.LockBits(New Rectangle(0, 0, Destination.Width, Destination.Height), Imaging.ImageLockMode.WriteOnly, Destination.PixelFormat) Dim stride = srcData.Stride Dim byteCount = stride * Source.Height Dim srcBytes(byteCount - 1) As Byte Dim destBytes(byteCount - 1) As Byte ' 复制源图像内存到数组 System.Runtime.InteropServices.Marshal.Copy(srcData.Scan0, srcBytes, 0, byteCount) ' 示例直接复制像素,可在此添加自定义处理逻辑 Array.Copy(srcBytes, destBytes, byteCount) ' 将处理后的数组复制回目标Bitmap System.Runtime.InteropServices.Marshal.Copy(destBytes, 0, destData.Scan0, byteCount) ' 解锁内存 Source.UnlockBits(srcData) Destination.UnlockBits(destData) e.Result = Destination End Sub
内容的提问来源于stack exchange,提问作者zomalaja
相关产品推荐
相关产品推荐

