我有一对Dictionary
,其对strings
和Bitmaps
对应于列出所有图像键的ListView
控件,以及其他信息。此外,我有一个PictureBox
,当列表视图的索引发生变化时,必须显示相应的字典图像。 Multiselect设置为false。 DateTime
就是为了确保只加载最新的“选定”图像。
当索引发生变化时,会发生以下其中一件事:
Picturebox
如何防止#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线程调用太慢(显然)所以我尝试从另一个线程执行它。我希望图像代表列表视图中最后选择的项目,但简单地召唤线程可能(并且会)导致竞争条件,所以我需要一种机制来防止/丢弃旧的选定索引更改图像,所以只有最后一个选定的索引决定加载哪个图像。
谢谢你的时间!