teebenson00 2014-05-06 08:37 采纳率: 0%
浏览 2437

C# 多线程读写删除文件并绘制在picture上

namespace PictureSD
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
bool flag;
bool flag2;
private Object thisLock = new object();
ComputePic face;
Thread ThreadSamp;// 图片

    Bitmap bc1;
    Bitmap bc2;
    Graphics gc1;
    private string dir = @"C:\Users\Teefan\Desktop\C#聊天\NEWFACElog\Camera\Camera\bin\Debug\Images\7.jpg";
    private string dir2 = @"C:\Users\Teefan\Desktop\C#聊天\NEWFACElog\Camera\Camera\bin\Debug\Images";
    private void button1_Click(object sender, EventArgs e)
    {
          System.Drawing.Image img= System.Drawing.Image.FromFile(dir);// 读7号图片测试    
          Bitmap imgBit = new Bitmap(img);
          SaveBit(imgBit, dir2, 2, "jpg");//存2号
          imgBit.Dispose();

          if (face == null)
          {
              ThreadSamp = new Thread(createSamp); // 计算人脸
              ThreadSamp.IsBackground = true;
              ThreadSamp.Start();                  
          }
                   ThreadSamp.Join();
                    bc1.Dispose();
                    gc1.Dispose();
                     string img2 = dir2 + "/" + 2.ToString() + ".jpg";
                     File.Delete(img2);           
    }

    class ComputePic
    {
        public int weight;
        public int height;
        public ComputePic(int a,int b)
        {
            weight = a;
            height = b;          
        }

    }
    private void createSamp()
    {       
            flag2 = false;
            face = new ComputePic(pictureBox1.Width, pictureBox1.Height);           
            //假定在计算
            bc1 = new Bitmap(dir2 + "/" + "2.jpg");
             gc1 = Graphics.FromImage(bc1);
            RectangleF rect1 = new RectangleF(10, 20, face.weight++, face.height++);
            gc1.DrawImage(bc1, 0, 0, rect1, GraphicsUnit.Pixel);             
        pictureBox1.Invoke((MethodInvoker)delegate //操作其他控件的语句
           {
                pictureBox1.Image = bc1;
                pictureBox1.Refresh();
          });

        face = null;
    }
    private bool SaveBit(Bitmap bitmap, string path, int num, string kind)
    {
        string img = path + "/" + num.ToString() + "." + kind;
        bitmap.Save(img);
        return flag = true;
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
      //  button1_Click(button1, null);
    }

    private void button2_Click(object sender, EventArgs e)
    {
        System.Timers.Timer t = new System.Timers.Timer(2000);   //实例化Timer类,设置间隔时间为10000毫秒;   
        t.Elapsed += new System.Timers.ElapsedEventHandler(button1_Click); //到达时间的时候执行事件;   
        t.AutoReset = true;   //设置是执行一次(false)还是一直执行(true);   
        t.Enabled = true;     
    }
}

}
是这样的,我做了一个界面想实现一个功能,相当于读7号图片,存时命名为2号,然后利用多线程计算2号图片,得到坐标,在绘制picture上,最后删除2号图片,再读7号,在2号计算、坐标、绘制。基本就是这个顺序不要乱,可是我琢磨几天了,要么gdi错误,要么bc1对象被别处引用,我不知道我这样的顺序应该怎么实现!或许很简单,可是我琢磨好久了,真心求教多线程而且能做到不会冲突的高手,我的代码只能基本实现图片删除,不能体现在picture画的样子刷新上!

  • 写回答

1条回答 默认 最新

  • 你知我知皆知 2024-08-02 01:23
    关注

    以下回答参考 皆我百晓生券券喵儿 等免费微信小程序相关内容作答,并由本人整理回复。

    你的代码看起来是一个非常复杂的应用程序,它涉及到多个不同的任务,包括图像处理、多线程编程和图形用户界面设计。为了帮助你解决问题,我将提供一些关键点和建议:

    问题描述与解决策略

    1. 多线程:确保在进行图像处理时使用正确的线程来避免内存泄漏和其他潜在的问题。

    2. 图像处理

      • 使用Graphics对象进行绘图。
      • 在多线程中,确保每次只有一个线程在绘制图像。
      • 对于计算2号图像,可以考虑将其作为另一个线程的任务,并且在主线程中等待计算结果。
    3. 多线程与内存管理

      • 确保在创建新线程时正确地释放旧线程的对象以避免内存泄露。
      • 使用锁或条件变量来协调不同线程之间的同步访问。
    4. 图形用户界面

      • 使用Invoke方法而不是this.Invoke方法,因为后者会阻止其他调用者对当前线程的控制权。
      • 使用委托来传递事件到子线程,以便子线程能够响应来自父线程的事件。
    5. 错误检查

      • 添加适当的错误处理机制,例如异常捕获和日志记录。
    6. 性能优化

      • 考虑使用缓存来减少重复计算,或者在计算完成后立即保存图像。

    示例代码示例

    以下是一个简化版的例子,展示了如何使用多线程进行图像处理和绘制:

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    class ImageProcessor
    {
        public static void ProcessImage(string imagePath, int x, int y, int width, int height, out Bitmap resultBitmap)
        {
            try
            {
                // Load the image and create a new bitmap with the same dimensions.
                using (var image = new Bitmap(imagePath))
                {
                    var result = new Bitmap(width, height);
    
                    // Draw the original image into the new bitmap.
                    using (var graphics = Graphics.FromImage(result))
                    {
                        graphics.DrawImage(image, 0, 0, width, height);
                    }
    
                    // Return the processed bitmap.
                    resultBitmap = result;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error processing image: {ex.Message}");
            }
        }
    }
    
    public partial class MainForm : Form
    {
        private readonly List<Thread> _threads = new List<Thread>();
        private readonly Dictionary<int, Bitmap> _processedImages = new Dictionary<int, Bitmap>();
    
        public MainForm()
        {
            InitializeComponent();
        }
    
        private void button1_Click(object sender, EventArgs e)
        {
            button1.Enabled = false;
            button2.Enabled = true;
    
            for (int i = 0; i < 10; i++)
            {
                var thread = new Thread(() =>
                {
                    try
                    {
                        // Create a temporary file to store the image data.
                        var tempFilePath = Path.GetTempFileName();
                        var image = Image.FromFile(tempFilePath);
                        var width = image.Width;
                        var height = image.Height;
    
                        // Calculate the coordinates of the bounding box around the face.
                        var left = (width / 2) - (image.Width / 2);
                        var top = (height / 2) - (image.Height / 2);
                        var right = left + image.Width;
                        var bottom = top + image.Height;
    
                        // Draw the face in the temporary file.
                        using (var graphics = Graphics.FromImage(image))
                        {
                            graphics.DrawRectangle(Pens.Black, left, top, right, bottom);
                        }
    
                        // Save the image as a JPEG file.
                        using (var stream = new FileStream(tempFilePath, FileMode.Create))
                        {
                            image.Save(stream, ImageFormat.Jpeg);
                        }
                    }
                    finally
                    {
                        // Delete the temporary file.
                        File.Delete(tempFilePath);
                    }
                });
                thread.Start();
                _threads.Add(thread);
            }
        }
    
        private void button2_Click(object sender, EventArgs e)
        {
            button2.Enabled = false;
            button1.Enabled = true;
    
            foreach (var thread in _threads)
            {
                thread.Join();
            }
    
            foreach (var image in _processedImages.Values)
            {
                image?.Dispose();
            }
    
            button1.Enabled = true;
            button2.Enabled = false;
        }
    }
    

    在这个例子中,我们首先从用户的点击事件中获取图像数据,并对其进行预处理。然后,我们将图像保存为JPEG格式,并通过主线程中的Join()方法等待所有子线程完成。

    注意,这只是一个基础版本,实际应用可能需要更复杂的错误处理、资源管理和性能优化。

    评论

报告相同问题?