public ConcurrentDrawingTest() { InitializeComponent(); _buttons = TreeHelper.GetLogicalChildren <Button>(this); // determine grid size defined in XAML int rows = HostGrid.RowDefinitions.Count; int columns = HostGrid.ColumnDefinitions.Count; // create one concurrent DrawingVisual per Grid cell _visualHosts = new ConcurrentVisualHost[rows * columns]; Func <Visual> createVisual = () => { return(new DrawingVisual()); }; for (int i = 0; i < _visualHosts.Length; i++) { ConcurrentVisualHost host = new ConcurrentVisualHost(createVisual); _visualHosts[i] = host; HostGrid.Children.Add(host); Grid.SetColumn(host, i % columns); Grid.SetRow(host, i / rows); DrawingVisual visual = (DrawingVisual)host.WorkerVisual; host.BeginWork(() => DrawName(visual)); } // concurrent threads require dedicated RNG instances int ticks = Environment.TickCount; _twisters = new MersenneTwister[_visualHosts.Length]; for (int i = 0; i < _twisters.Length; i++) { _twisters[i] = new MersenneTwister((uint)(ticks + i)); } }
private void DrawAllContents(bool isConcurrent) { // show how long GUI thread is inactive foreach (Button button in _buttons) { button.IsEnabled = false; } Dispatcher.DoEvents(); // determine actual size of each grid cell _cellWidth = (int)HostGrid.ColumnDefinitions[0].ActualWidth; _cellHeight = (int)HostGrid.RowDefinitions[0].ActualHeight; for (int i = 0; i < _visualHosts.Length; i++) { ConcurrentVisualHost host = _visualHosts[i]; DrawingVisual visual = (DrawingVisual)host.WorkerVisual; MersenneTwister twister = _twisters[i]; Action action = () => DrawContent(visual, twister); if (isConcurrent) { host.WorkerDispatcher.BeginInvoke(action); } else { host.WorkerDispatcher.Invoke(action); } } // GUI thread becomes active again foreach (Button button in _buttons) { button.IsEnabled = true; } }