0

我有一个Dictionary与对stringsBitmaps对应的ListView控件,该控件列出了所有图像键以及其他信息。当列表视图的索引更改时,我还有一个PictureBox必须显示字典的相应图像。多选设置为假。DateTime那里是为了确保仅加载最新的“选定”图像。

当索引更改时,会随机发生以下情况之一:

  1. 图片加载正确
  2. 不会发生变化Picturebox
  3. 抛出 System.ArgumentException。异常总是在同一行抛出(见代码)

如何防止 #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 线程调用太慢(显然),所以我尝试从另一个线程执行它。我希望图像代表列表视图上最后一个选定的项目,但简单地调用线程可能(并且会)导致竞争条件,所以我需要一种机制来防止/丢弃旧的选定索引更改图像,所以只有最后一个选定的索引决定加载哪个图像。

谢谢你的时间!

4

0 回答 0