private void Button_Click(object sender, RoutedEventArgs e) { CreateElementOnSeperateThread(() => { var loadsOfItems = new List<int>(); for (var i = 0; i < 100000; i++) loadsOfItems.Add(i + 12); var dataGrid = new DataGrid { ItemsSource = loadsOfItems, Width = 500, Height = 500 }; dataGrid.Measure(new Size(500, 500)); dataGrid.Arrange(new Rect(0, 0, 500, 500)); return dataGrid; }, result => SampleGrid1.Children.Add(result)); } public void CreateElementOnSeperateThread(Func<UIElement> constructObject, Action<UIElement> constructionCompleted) { VerifyAccess(); // save dispatchers for future usage. // we create new element on a seperate STA thread // and then basically swap UIELEMENT's Dispatcher. Dispatcher threadDispatcher = null; var currentDispatcher = Dispatcher.CurrentDispatcher; var ev = new AutoResetEvent(false); var thread = new Thread(() => { threadDispatcher = Dispatcher.CurrentDispatcher; ev.Set(); Dispatcher.Run(); }); thread.SetApartmentState(ApartmentState.STA); thread.IsBackground = true; thread.Start(); ev.WaitOne(); threadDispatcher.BeginInvoke(new Action(() => { var constructedObject = constructObject(); currentDispatcher.BeginInvoke(new Action(() => { var fieldinfo = typeof(DispatcherObject).GetField("_dispatcher", BindingFlags.NonPublic | BindingFlags.Instance); if (fieldinfo != null) fieldinfo.SetValue(constructedObject, currentDispatcher); constructionCompleted(constructedObject); threadDispatcher.BeginInvokeShutdown(DispatcherPriority.Normal); }), DispatcherPriority.Normal); }), DispatcherPriority.Normal); }