图像保存尝试读取或写入受保护的内存错误

时间:2018-02-23 15:14:54

标签: c# multithreading image

我绝望地为我的代码找到了解决方案。我使用backgroundworker在一个线程中运行它。和img.Save频繁(并非总是)给出此错误。

image1.Save(ms1, imageCodecInfo, parametreler);
  

尝试读取或写入受保护的内存。这通常是一个   表明其他内存已损坏。

     

在   System.Drawing.SafeNativeMethods.Gdip.GdipSaveImageToStream(HandleRef   图像,IStream流,Guid& classId,HandleRef encoderParams)at   System.Drawing.Image.Save(Stream stream,ImageCodecInfo encoder,   EncoderParameters encoderParams)at   Project.Forms.Degerlendirme.EditProductPhotosForm.backgroundWorker_uploader2_DoWork(对象   发件人,DoWorkEventArgs e)in   C:\用户\了Umut \ NETProjects \项目\形式\促销\ EditProductPhotosForm.cs:线   654在   System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
  在System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object   论证)   System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr的   md,Object [] args,Object server,Object []& outArgs)at   System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(即时聊天   msg,IMessageSink replySink)at   System.Runtime.Remoting.Proxies.AgileAsyncWorkerItem.ThreadPoolCallBack(对象   o)at   System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(对象   国家)   System.Threading.ExecutionContext.RunInternal(执行上下文   executionContext,ContextCallback回调,对象状态,布尔值   preserveSyncCtx)at   System.Threading.ExecutionContext.Run(执行上下文   executionContext,ContextCallback回调,对象状态,布尔值   preserveSyncCtx)at   System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()   在System.Threading.ThreadPoolWorkQueue.Dispatch()at   System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

我阅读并尝试了每一篇文章,但他们都没有帮助我。我想我错过了一点。这是我的代码。

    private void backgroundWorker_uploader1_DoWork(object sender, DoWorkEventArgs e)
    {
        object[] parameters = e.Argument as object[];
        string fileName = parameters[1] as string;
        string filePath = parameters[4] as string;

        using (Image image1 = parameters[0] as Image)
        using (MemoryStream ms1 = new MemoryStream())
        {
            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
            ImageCodecInfo imageCodecInfo = null;

            foreach (ImageCodecInfo codec in codecs)
            {
                if (codec.MimeType == "image/jpeg")
                    imageCodecInfo = codec;
            }

            EncoderParameters parametreler = new EncoderParameters(1);
            parametreler.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)100);
            //Object imageLock1 = new Object();

            lock (image1)
            {
                image1.Save(ms1, imageCodecInfo, parametreler);
            }

            using (Image img1 = Image.FromStream(ms1))
            {
                bool sonuc = HelperActions.UploadImgToFTPfromImage(fileName, img1);
                if (sonuc == true)
                {
                    e.Result = new object[6] { this, prevForm, true, (int)parameters[5], (int)parameters[2], (int)parameters[3] };
                }
                else
                {
                    e.Result = new object[6] { this, prevForm, false, (int)parameters[5], (int)parameters[2], (int)parameters[3] };
                }
            }
        }
    }

这就是我称之为背景工作者的方式。我有6个,他们的dowork事件几乎相同。

       for (int i = 0; i < mappings.Count; i++)
        {
            Picture picture = mappings[i].Picture as Picture;
            if (picture == null)
                continue;

            mappings[i].DisplayOrder = (int)numUpDowns[i].Value - 1;
            entities.Product_Picture_Mapping.AddOrUpdate(mappings[i]);

            string fileName = HelperActions.CreateImgFileName(picture);
            string filePath = "";

            object obje11 = picEdits[i].Image as Image;
            object obje12 = fileName;
            object obje13 = picture.Id;
            object obje14 = i + 1;
            object obje15 = filePath;
            object obje16 = productId;
            object[] parameters = new object[6] { obje11, obje12, obje13, obje14, obje15, obje16 };
            try
            {
                switch (i)
                {
                    case 0:
                        backWorker1_uploader.RunWorkerAsync(parameters);
                        break;
                    case 1:
                        backWorker2_uploader.RunWorkerAsync(parameters);
                        break;
                    case 2:
                        backWorker3_uploader.RunWorkerAsync(parameters);
                        break;
                    case 3:
                        backWorker4_uploader.RunWorkerAsync(parameters);
                        break;
                    case 4:
                        backWorker5_uploader.RunWorkerAsync(parameters);
                        break;
                    case 5:
                        backWorker6_uploader.RunWorkerAsync(parameters);
                        break;
                    default:
                        break;
                }
            }
            catch (Exception ex)
            {
                if (!backgroundWorkerYedek.IsBusy)
                {
                    backgroundWorkerYedek.RunWorkerAsync(parameters);
                    Console.WriteLine("Yedek Çalıştırıldı");
                }
                else
                {
                    MessageBox.Show(i + " nolu - " + ex.Message);
                }   
            }
            System.Threading.Thread.Sleep(200);
        }
        entities.SaveChanges();

1 个答案:

答案 0 :(得分:1)

只需查看文档:{​​{3}}

根据该帖子,你不能同时使用GDI +,而是可以使用WPF进行成像操作。您的所有GDI +操作都有WPF对应项,但您必须四处寻找如何做到这一点。

编辑:或者,作为一个工作区,锁定一个静态对象以有效地序列化所有GDI +的使用

static object _syncRoot = new object();

并在你的锁定语句中使用它来构建bacground工作线程

lock (_syncRoot)

MS post on GDI+ and concurrency

编辑2:如果您可以确保多个线程只使用一个static实例,则您不需要_syncRoot_syncRoot可以是类的私有成员,也可以启动后台线程。