I am trying to save a DataGridView as png. I added a button to the DataGridView which should do this but i always get this error:
Cross-thread operation not valid: Control 'phrasesDataGridView' accessed from a thread other than the thread it was created on on this line: phrasesDataGridView.DrawToBitmap(bitmap, new System.Drawing.Rectangle(0, 0, this.phrasesDataGridView.Width, this.phrasesDataGridView.Height));
The error i get is Cross-thread operation not valid: Control 'phrasesDataGridView' accessed from a thread other than the thread it was created on
I tried to follow some advice here: enter link description here But whatever i try I don't get the error anymore but my app hangs.
My raw code without any changes looks like this:
private void SavePng_Click(object sender, EventArgs e)
{
if (phrasesDataGridView.Rows.Count > 0)
{
var t = new Thread((ThreadStart)(() =>
{
var sfd = new SaveFileDialog();
sfd.Filter = "PNG (*.png)|*.png";
sfd.FileName = "Phrases.png";
var fileError = false;
if (sfd.ShowDialog() == DialogResult.OK)
{
if (File.Exists(sfd.FileName))
{
try
{
File.Delete(sfd.FileName);
}
catch (IOException ex)
{
fileError = true;
Console.Beep();
MessageBox.Show("Unable to write to file." + ex.Message);
}
}
if (!fileError)
{
try
{
var bitmap = new Bitmap(this.phrasesDataGridView.Width, this.phrasesDataGridView.Height);
phrasesDataGridView.DrawToBitmap(bitmap, new System.Drawing.Rectangle(0, 0, this.phrasesDataGridView.Width, this.phrasesDataGridView.Height));
bitmap.Save(sfd.FileName);
Console.WriteLine(sfd.FileName);
}
catch (Exception ex)
{
Console.Beep();
}
}
}
}));
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
}
else
{
MessageBox.Show("Unable to save Phrase file", "Save as PDF");
}
}
It hanged in this line i tried to add:
phrasesDataGridView.Invoke(dt => dt.DrawToBitmap(bitmap, new System.Drawing.Rectangle(0, 0, this.phrasesDataGridView.Width, this.phrasesDataGridView.Height)));
And this Extension:
public static class Extensions
{
public static void Invoke<TControlType>(this TControlType control,
Action<TControlType> del)
where TControlType : Control
{
if (control.InvokeRequired)
control.Invoke(new Action(() => del(control)));
else
del(control);
}
}