The essence of the problem: to write a program that, when you press the left arrow on the keyboard, creates a pop-up tooltip with a growing numerical sequence (1 .... 50000) in the place pointed by the cursor. The main condition is the creation of a thread for each pop-up prompt that will process this hint.

The problem itself is that the objects of the Popup class are not displayed in the window, although the threads are executed. If anyone can point out errors or suggest a literature / source on this topic, I would be very grateful.

Code example:

 //Лист, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΠΎ надобности Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ ΠΏΠΎΡ‚ΠΎΠΊΠΈ List < Thread > MyThreads = new List < Thread > (); public void StartPopThread(object obj) { Popup temp = new Popup(); ParamsOfPop FromMain = new ParamsOfPop(); FromMain = (ParamsOfPop) obj; TextBlock txt = new TextBlock(); txt.Background = Brushes.Black; txt.Text = "0"; temp.Child = txt; temp.IsOpen = true; while (FromMain.currenValue < 50000) { temp.Child = txt; txt.Text = FromMain.currentValue.ToString(); FromMain.currentValue++; temp.HorizontalOffset = FromMain.x + FromMain.Left; temp.VerticalOffset = FromMain.y + FromMain.Top; Thread.Sleep(1000); } } private void Window_KeyDown(object sender, KeyEventArgs e) { Point MousPos = Mouse.GetPosition(null); //созданиС ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΏΠΎ Π½Π°ΠΆΠ°Ρ‚ΠΈΡŽ Π»Π΅Π²ΠΎΠΉ клавиши if (e.Key == Key.Left) { MyThreads.Add(new Thread(new ParameterizedThreadStart(StartPopThread))); double a = MousPos.X; double b = MousPos.Y; ParamsOfPop Send = new ParamsOfPop(a, b, this.Top, this.Left); MyThreads[MyThreads.Count - 1].SetApartmentState(ApartmentState.STA); MyThreads[MyThreads.Count - 1].Start(Send); } } class ParamsOfPop { public double x; public double y; public double Top; public double Left; public UInt32 currentValue = 0; public ParamsOfPop() { x = 0; y = 0; } public ParamsOfPop(double a, double b, double c, double d) { this.x = a; this.y = b; this.Top = c; this.Left = d; } } 

StartPopThread is a function on the basis of which a thread is created to process the Popup object. class ParamsOfPop is a class that passes cursor parameters to a stream.

  • Is this a learning task? If not, where does such a strange demand for individual flows come from? - VladD
  • Yes, this is a learning task. Without threads, I managed to implement it, but not with them. - Egor
  • Hmm, where do you show the popup? You only created it. - VladD
  • The visualization itself was written in WPF. There the output was carried out through the property IsOpen - Egor
  • Ok, and what happens when you install IsOpen ? Show this part, it’s important, I think. - VladD

1 answer 1

You forgot to start the dispatcher in a new thread. (In the main thread, WPF runs it for you.) The fact is that WPF has a dispatcher that is automatically launched for you by the framework in the main thread. But in the side threads you have to start it yourself and complete it yourself.

A dispatcher is essentially a message loop, which processes window messages and starts drawing controls in the background.

To run the dispatcher, you need to run Dispatcher.Run . This is a blocking function, so I added the Work command to the queue of the not yet started dispatcher before launching the dispatcher.

The next subtlety is that you cannot block a thread using Thread.Sleep , the message loop must spin for the UI to be redrawn. There are many ways to do it right. For example, DispatcherTimer . But the most correct one is await task.Delay .

You can, for example, use DispatcherThread from here . Here is an example cut to a minimum:

 public class DispatcherThread { public DispatcherThread() { var thread = new Thread(() => { var d = Dispatcher.CurrentDispatcher; d.InvokeAsync(Work); Dispatcher.Run(); }); thread.SetApartmentState(ApartmentState.STA); thread.Start(); } async void Work() { await Task.Yield(); // ΠΏΠΎΠ΄ΠΎΠΆΠ΄Ρ‘ΠΌ, ΠΏΠΎΠΊΠ° диспСтчСр стартуСт TextBlock tb = new TextBlock() { Background = Brushes.HotPink, Foreground = Brushes.Black }; Popup p = new Popup() { Child = tb, IsOpen = true HorizontalOffset = 100, VerticalOffset = 100, Placement = PlacementMode.AbsolutePoint }; for (int i = 0; i < 20; i++) { tb.Text = "Iteration #" + i; await Task.Delay(1000); // Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ } // Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅ΠΌ Ρ†ΠΈΠΊΠ» сообщСний, это Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ ΠΈ Π²Ρ‹Π·ΠΎΠ² Dispatcher.Run, // Π° с Π½ΠΈΠΌ ΠΈ вСсь ΠΏΠΎΡ‚ΠΎΠΊ Dispatcher.CurrentDispatcher.InvokeShutdown(); } } 
  • Thank you very much. I'm going to change the code. - Egor
  • @ Egor: Please! Good luck to you! - VladD