0

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);
        }
    }
dandan
  • 509
  • 3
  • 8
  • 21
  • 1
    Why even use a thread? And why combine it with a DialogBox?? There errors ought to be clear, no? Aslo: There is a difference between an app that hangs and the error you get.. – TaW Aug 29 '20 at 11:27
  • Where does it hang? You can find location from menu : Debug : Break All. Then menu : Debug : Windows : Call Stack. – jdweng Aug 29 '20 at 11:29
  • If i don't use a thread i cannot even send the datagridview - i got another error so i had to use this: t.SetApartmentState(ApartmentState.STA); t.Start(); t.Join(); – dandan Aug 29 '20 at 11:31
  • [Save whole of DataGridView as an Image](https://stackoverflow.com/a/53484089/7444103) -- [Create a Tiff Bitmap file from a DatagridView](https://stackoverflow.com/a/59633044/7444103). Remove that thread. – Jimi Aug 29 '20 at 11:45
  • if i dont use a thread i get this error when i try to call the "ShowDialo" for the browse for file method: be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it. This exception is only raised if a debugger is attached to the process.' – dandan Aug 29 '20 at 12:00
  • You get the exception because you're trying to open a Dialog in a Thread other than the UI Thread and this new Thread is not `STA`. You don't need threads, so remove everything thread-related. – Jimi Aug 29 '20 at 12:06
  • i tried - still get the error for the var sfd = new SaveFileDialog(); line. perhaps i will just use this in a thread. in this case how can i get the result - the filename back to my app? – dandan Aug 29 '20 at 12:13
  • _If i don't use a thread i cannot even send the datagridview_ Incorrect. Do not use threads for any interaction with the gui! – TaW Aug 29 '20 at 13:27
  • @TaW i meant that without using thread i cannot open the ShowDialog for the browse button to set the file name. – dandan Aug 29 '20 at 15:36
  • _I meant that without using thread i cannot open the ShowDialog_ yes, but this is wrong. If you experience this, something else is seriously wrong in your program. – TaW Aug 29 '20 at 17:53

0 Answers0