更改图像时PictureBox会抛出异常

时间:2013-06-25 23:33:59

标签: c# multithreading exception dictionary picturebox

我有一对Dictionary,其对stringsBitmaps对应于列出所有图像键的ListView控件,以及其他信息。此外,我有一个PictureBox,当列表视图的索引发生变化时,必须显示相应的字典图像。 Multiselect设置为false。 DateTime就是为了确保只加载最新的“选定”图像。

当索引发生变化时,会发生以下其中一件事:

  1. 图片正确加载
  2. Picturebox
  3. 未发生任何变化
  4. 抛出System.ArgumentException。异常总是抛出在同一行(见代码)
  5. 如何防止#2和#3发生?

    以下是代码:

    private Dictionary<string, Bitmap> dictionary;
    private ReaderWriterLockSlim dictionary_lock;
    
    private DateTime _LAST_PREVIEW_UPDATE;
    private DateTime LAST_PREVIEW_UPDATE
    {
        get { return _LAST_PREVIEW_UPDATE; }
        set 
        {
            if(value.CompareTo(_LAST_PREVIEW_UPDATE) < 0)
                _LAST_PREVIEW_UPDATE = value; 
        }
    }
    
    /* ... */
    
    private void listView1_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (this.listView1.SelectedItems.Count != 1)
            return;
    
        DateTime now = DateTime.Now;
        string image_code = this.listView1.SelectedItems[0].SubItems[0].Text;
    
        Thread t = new Thread(() =>
        {
            Bitmap image = null;
            bool load_properly;
    
            dictionary_lock.EnterReadLock();
            try
            {
                load_properly = dictionary.TryGetValue(image_code, out image);
            }
            finally
            {
                dictionary_lock.ExitReadLock();
            }
    
            if (!load_properly)
            {
                /* LOG THE ERROR */
                return;
            }
    
            this.BeginInvoke((MethodInvoker)delegate
            {
                if (now.CompareTo(LAST_PREVIEW_UPDATE) > 0)
                {
                    LAST_PREVIEW_UPDATE = now;
                    if (picturebox.Image != null)
                        picturebox.Image.Dispose();
                    picturebox.Image = image; // This throws the exception
                }
            });
        });
    
        lock (picturebox)
        {
            t.Start();
            t.Join(3000);
        }
    }
    

    编辑:这是调用堆栈

        System.Drawing.dll!System.Drawing.Image.FrameDimensionsList.get() + 0x258 bytes 
        System.Drawing.dll!System.Drawing.ImageAnimator.CanAnimate(System.Drawing.Image image) + 0x6d bytes 
        System.Drawing.dll!System.Drawing.ImageAnimator.ImageInfo.ImageInfo(System.Drawing.Image image) + 0x26 bytes    
        System.Drawing.dll!System.Drawing.ImageAnimator.Animate(System.Drawing.Image image, System.EventHandler onFrameChangedHandler) + 0x97 bytes 
        System.Windows.Forms.dll!System.Windows.Forms.PictureBox.Animate(bool animate) + 0x65 bytes 
        System.Windows.Forms.dll!System.Windows.Forms.PictureBox.InstallNewImage(System.Drawing.Image value, System.Windows.Forms.PictureBox.ImageInstallationType installationType) + 0xc8 bytes   
    >   Application.exe!Application.FrmMain.listView1_SelectedIndexChanged.AnonymousMethod__a() Line 596 + 0x78 bytes   C#
    

    EDIT2:我想实现之前解释过的功能,但这是我能得到的更好的方法。直接从UI线程调用太慢(显然)所以我尝试从另一个线程执行它。我希望图像代表列表视图中最后选择的项目,但简单地召唤线程可能(并且会)导致竞争条件,所以我需要一种机制来防止/丢弃旧的选定索引更改图像,所以只有最后一个选定的索引决定加载哪个图像。

    谢谢你的时间!

0 个答案:

没有答案