場景:這是在一個WinForm專案中查看帶有一些額外相關資料的影像,用戶可以通過listBox在影像之間切換,所有影像的資料都存盤在一個DataTable中,每次用戶更改listBox的選定索引,SelectedIndexChanged()將找到具有所選img名稱的影像的DataRow,并且最初所有影像的DataTable都不包含解析度資料,所以我試圖讀取影像解析度并保存到所選的DataRow(實際上將“Resolution”值從"" 以 600 為例),我將 DataRowcurrentGSImgInfo設為欄位變數,每次 selectedIndex 更改時,它都會分配新值,代碼如下(全部在里面SelectedIndexChanged()):
imgDir = baseDir "\\TestDir\\" selectedGSImgName ".jpg"; //TODO Dir
gsBitmapOri = new Bitmap(imgDir);//Get original bitmap
Bitmap initGSViewBitmap = new Bitmap(gsBitmapOri, new Size((int)(gsBitmapOri.Width * 0.066), (int)(gsBitmapOri.Height * 0.066)));
gsBitmapCur = initGSViewBitmap;
gsZoomFactor = 0.066;
gsManualAdjust = false; //Initialize to enable auto adjust.
currentGSImgLocation = new Point(0, 0);
this.txtBox_startDepth.Text = "";//After change, re-initialize textual data
this.txtBox_endDepth.Text = "";
currentGSImgInfo = GSImgInfoOri.Select("coreNum = '" this.listBox_selectGSImg.Text "'")[0];
float imgDpi = gsBitmapOri.HorizontalResolution;
currentGSImgInfo.BeginEdit();
currentGSImgInfo[6] = imgDpi; //Where "resolution" is
currentGSImgInfo.EndEdit();
currentGSImgInfo.AcceptChanges();
GC.Collect(); //Recycle previous img from RAM
pictureBox_GS.Invalidate();
問題是,當代碼運行到 時currentGSImgInfo.EndEdit(),如果我不設定斷點,它只會繼續執行,導致程式沒有回應,但是如果我在selectedIndexChanged()函式開頭設定斷點,它會到達該斷點并執行直到EndEdit()再次到達斷點。“解析度”的值已正確更改。更糟糕的是,當程式第一次運行,第一次selectedIndexChanged()呼叫時,完全沒有問題,它成功執行currentGSImgInfo.EndEdit();并執行下一步預期的任何操作,但是當我選擇下一個 img 時,問題就出現了。我沒有系結currentGSImgInfo任何組件,它只用于存盤當前影像的資料,我該如何解決這個問題?
uj5u.com熱心網友回復:
您可以嘗試以下方法:
private bool BusySelectedIndexChanged; // used later to avoid re-entrancy
private void listBox_SelectedIndexChanged(object sender, EventArgs e)
{
// REENTRANCY
if (BusySelectedIndexChanged) // already running
return;
BusySelectedIndexChanged = true; // prevent re-entrancy
try
{
imgDir = baseDir "\\TestDir\\" selectedGSImgName ".jpg"; //TODO Dir
gsBitmapOri = new Bitmap(imgDir);//Get original bitmap
Bitmap initGSViewBitmap = new Bitmap(gsBitmapOri, new Size((int)(gsBitmapOri.Width * 0.066), (int)(gsBitmapOri.Height * 0.066)));
gsBitmapCur = initGSViewBitmap;
gsZoomFactor = 0.066;
gsManualAdjust = false; //Initialize to enable auto adjust.
currentGSImgLocation = new Point(0, 0);
this.txtBox_startDepth.Text = "";//After change, re-initialize textual data
this.txtBox_endDepth.Text = "";
float imgDpi = gsBitmapOri.HorizontalResolution;
currentGSImgInfo = GSImgInfoOri.Select("coreNum = '" this.listBox_selectGSImg.Text "'")[0];
// REALLY CHANGED ?
// Only if value is changing
if (imgDpi != currentGSImgInfo[6])
{
currentGSImgInfo.BeginEdit();
currentGSImgInfo[6] = imgDpi; //Where "resolution" is
currentGSImgInfo.EndEdit();
currentGSImgInfo.AcceptChanges();
}
GC.Collect(); //Recycle previous img from RAM
pictureBox_GS.Invalidate();
}
finally
{
BusySelectedIndexChanged = false;
}
}
它通過設定和清除欄位來避免重入BusySelectedIndexChanged:if/try/finally 塊確保內部代碼永遠不會在無限回圈中運行。
根據您的需要,可能會在 if/try/finally 塊之前移動一些代碼(在"// REENTRANCY"之前)。無限回圈的真正原因可能在其他地方。例如,某些由 EndEdit/AcceptChanges 觸發的事件反過來會更改串列框內的索引:這通常在串列框被清除并重新填充時發生。
獎勵:不要忘記 Dispose 臨時IDisposable物件(如initGSViewBitmap)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/475054.html
