I need to populate a column in a DataGridView with a thumbnail image. I would like to load the DataGridViewImageCell.Value **asynchronously** as it does take some time to download the images.

This solution loads the images asynchronously, but it appears to prevent the UI thread from performing other tasks (I assume because the application's message queue is filled with the .BeginInvoke calls).

How can this be accomplished yet still allow the user to scroll through the grid while images are being downloaded?

```
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; }
}

```