我需要用縮略圖填充DataGridView中的列。我想加載DataGridViewImageCell.Value 異步,因爲它需要一些時間來下載圖像。DataGridViewImageCell異步圖像加載
該解決方案異步加載圖像,但它似乎阻止UI線程執行其他任務(我假設因爲應用程序的消息隊列充滿了.BeginInvoke調用)。
如何做到這一點,但仍然允許用戶在圖像下載時滾動網格?
private void LoadButton_Click(object sender, EventArgs e)
{
myDataGrid.Rows.Clear();
// populate with sample data...
for (int index = 0; index < 200; ++index)
{
var itemId = r.Next(1, 1000);
var row = new DataGridViewRow();
// itemId column
row.Cells.Add(new DataGridViewTextBoxCell
{
ValueType = typeof(int),
Value = itemId
});
// pix column
row.Cells.Add(new DataGridViewImageCell
{
ValueType = typeof(Image),
ValueIsIcon = false
});
// pre-size height for 90x120 Thumbnails
row.Height = 121;
myDataGrid.Rows.Add(row);
// Must be a "better" way to do this...
GetThumbnailForRow(index, itemId).ContinueWith((i) => SetImage(i.Result));
}
}
private async Task<ImageResult> GetThumbnailForRow(int rowIndex, int itemId)
{
// in the 'real world' I would expect 20% cache hits.
// the rest of the images are unique and will need to be downloaded
// emulate cache retrieval and/or file download
await Task.Delay(500 + r.Next(0, 1500));
// return an ImageResult with rowIndex and image
return new ImageResult
{
RowIndex = rowIndex,
Image = Image.FromFile("SampleImage.jpg")
};
}
private void SetImage(ImageResult imageResult)
{
// this is always true when called by the ContinueWith's action
if (myDataGrid.InvokeRequired)
{
myDataGrid.BeginInvoke(new Action<ImageResult>(SetImage), imageResult);
return;
}
myDataGrid.Rows[imageResult.RowIndex].Cells[1].Value = imageResult.Image;
}
private class ImageResult
{
public int RowIndex { get; set; }
public Image Image { get; set; }
}
您可以爲1個圖像丟棄任務,並在此任務結束時加載下一個並一次又一次加載到最後一個圖像。 – McNets
我不知道是否沒有答案?似乎任何解決方案都會將消息發送到UI線程,從而窒息其處理用戶消息的能力。我可以通過增加「模擬」延遲來測試。 – Tony
測試結果 - 我只是將模擬的延遲時間增加到5000-7500 mS,我能夠在網格中導航約5秒,然後在圖像填充後鎖定。 Hmmmm。 – Tony