If your function is long and works with UI objects, you are doing wrong. It is necessary to unload long-term work into other streams in order not to block the main stream. So that your code can still interact with the UI, you can use either async / await , or Dispatcher.InvokeAsync , or IProgress .
Examples:
async / await :
async Task MoveObjects() { // собираем данные в UI-потоке var currentPositions = Arena.Children.Select(child => new Point(Canvas.GetX(child), Canvas.GetY(child))).ToList(); for (int i = 0; i < 100; i++) { // вычисляем новые данные в новом потоке var newPositions = await Task.Run(() => engine.ComputeNextPositions(currentPositions)); // присваиваем данные UI-объектам в UI-потоке for (int i = 0; i < Arena.Children.Count; i++) { var child = Arena.Children[i]; var coord = newPositions[i]; Canvas.SetX(child, coord.X); Canvas.SetY(child, coord.Y); } currentPositions = newPositions; await Task.Delay(25); } }
Dispatcher.InvokeAsync :
Task MoveObjects() { var objects = Arena.Children.ToList(); return Task.Run(() => MoveObjectsInBackground(objects, Dispatcher)); } async Task MoveObjectsInBackground(List<UIElement> objects, Dispatcher dispatcher) { // собираем данные в UI-потоке var currentPositions = await dispatcher.InvokeAsync(() => objects.Select(child => new Point(Canvas.GetX(child), Canvas.GetY(child))).ToList()); for (int i = 0; i < 100; i++) { // вычисляем новые данные var newPositions = ComputeNewPositions(currentPositions); // отправляем их в UI-поток await dispatcher.InvokeAsync(() => { for (int i = 0; i < objects.Count; i++) { var child = objects[i]; var coord = newPositions[i]; Canvas.SetX(child, coord.X); Canvas.SetY(child, coord.Y); } }); await Task.Delay(25); } }
IProgress :
Task MoveObjects() { // собираем данные в UI-потоке var positions = Arena.Children.Select(child => new Point(Canvas.GetX(child), Canvas.GetY(child))).ToList(); var progress = new Progress<List<Point>>(UpdatePositions); await Task.Run(() => MoveObjectsInBackground(positions, progress); } void UpdatePositions(List<Point> positions) { for (int i = 0; i < Arena.Children.Count; i++) { var child = Arena.Children[i]; var coord = newPositions[i]; Canvas.SetX(child, coord.X); Canvas.SetY(child, coord.Y); } } void MoveObjectsInBackground(List<Point> positions, IProgress<List<Point>> progress) { for (int i = 0; i < 100; i++) { var newPositions = ComputeNewPositions(currentPositions); progress.Report(newPositions); currentPositions = newPositions; Thread.Sleep(25); } }