0

I know that this subject has already been treated several times but the codes presented are for the most part very complicated and do not correspond or little to mine. So my problem is that when executing my code I get the error message of the title

I have a datagrid in my main thread that I want to modify in the secondary thread:

private void BtnThread_Click(object sender, RoutedEventArgs e)
        {
            thread = new Thread(new ThreadStart(ThreadLoop));
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
        }
        public void ThreadLoop()
        {
            DateTime? dtdebTemp = new DateTime();
            DateTime? dtfinTemp = new DateTime();
            DataGrid dg = new DataGrid();
            DataGridTextColumn col = new DataGridTextColumn();
            col.Header = "test";
            Application.Current.Dispatcher.Invoke(new Action(() =>
            {
                dtdebTemp = dtDeb.Value;
                dtfinTemp = dtFin.Value;
                dg = MyDataGridOfMainThread;
            }));
            dg.Columns.Add(col);
        }

I'm trying for the moment just to add a test column but it's impossible. Thank you for your future answer.


Edit :

I found the answer it was enough to make the modification of the datagrid inside a Dispatcher like this :

public async void ThreadLoop()
        {
            DateTime? dtdebTemp = new DateTime();
            DateTime? dtfinTemp = new DateTime();
            DataGrid dg = new DataGrid();
            DataGridTextColumn col = new DataGridTextColumn();
            col.Header = "test";
            Application.Current.Dispatcher.Invoke(new Action(() =>
            {
                dtdebTemp = dtDeb.Value;
                dtfinTemp = dtFin.Value;
                dg = MyDataGridOfMainThread;
            }));
            await this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
                        {
                            dg.Columns.Add(col);
                        }, null);
        }
Quentin Couderc
  • 86
  • 2
  • 12
  • Why are you creating a `Grid` in code behind? And why is it in a background thread? Have you heard of `DataTemplates`? – XAMlMAX Jul 17 '19 at 15:39
  • my grid is create with xaml, I feed it with the data of a webservice, and the columns display is editable by the user, so I want to load the data and columns in the thread so that the window does not freeze while loading the data and the creation of columns. – Quentin Couderc Jul 17 '19 at 15:46
  • The problem is you can't write to the GUI from a non GUI thread. That's what the error message tells you "The calling thread can not access this object because another thread owns it". With object it means your `DataGrid`. – Mardukar Jul 17 '19 at 15:52
  • 2
    Use Binding instead! You can load data in the background thread. Using code behind will cause you more trouble than it's worth. Read up on MVVM and Binding in WPF. Otherwise you will have to solve problem after problem. – XAMlMAX Jul 17 '19 at 15:55
  • 1
    Ok, I am currently an apprentice in a company so I will wait for the help of my superiors because they help me a lot on the structure of my project and I mainly used the code behind compared the xaml. Thank you for your help, good evening to you. – Quentin Couderc Jul 17 '19 at 16:01
  • You can't mix UI elements that are created in different threads. – Clemens Jul 17 '19 at 16:11
  • No worries, if you spend some time learning the MVVM and WPF then you will be saving time in the long run. It takes a while, but it is WORTH it! :-) – XAMlMAX Jul 17 '19 at 16:11
  • If you need work to be done off the main thread (the UI thread), use `await Task.Run(...)` – Clemens Jul 17 '19 at 16:16

1 Answers1

-1

this is because can't access object out thread. You need use delegate for access. https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/reference-types

  • I don't understand where to use delegate, can you give me more details please ? – Quentin Couderc Jul 17 '19 at 15:48
  • This answer makes no sense, and the link goes to the italian version of Microsoft Docs !? – Clemens Jul 17 '19 at 16:20
  • All the UI controls have thread affinity they cannot be updated from any other thread. UI controls can be updated only by same thead it has created it. To update the UI controls u have to post a message to UI thread and UI thread will execute it for. Message can posted using the dispatcher. Dispatcher is message queue owned by the UI thread. In your threadpool method where ever your updating the UI control all those needs to updated using dispatcher. You can obtain dispatcher object from the property be Application.Current.CurrentDispatcher. you can pass delegate to invoke method of dispatche – Kumareshan Jul 17 '19 at 16:45
  • try this this.Invoke((MethodInvoker)delegate { dg.Columns.Add(col); }); – christian gobbi Sep 11 '19 at 09:06