Reject stuttering--use multithreading to update the UI in WPF

Source: Internet
Author: User

Experienced handlers know that it is not possible to take time-consuming actions on the UI thread, which can cause the interface to stutter, as a simple example:

????PublicPartialClassMainWindow:Window
???? {
????????PublicMainWindow ()
???????? {
???????????? InitializeComponent ();
????????????thisnewAction< Span style= "Color:black" > (() = {}));
???????????? this????????}

???????? privatevoid mainwindow_loaded (object sender, Span style= "COLOR: #2b91af" >routedeventargs e)
???????? {
???????????? thisnewusercontrol1 ();
????????}
????}
/span>
????ClassUserControl1:UserControl
???? {
????????TextBlockTextBlock;

????????PublicUserControl1 ()
???????? {
???????????? TextBlock =NewTextBlock();
????????????This
???????????? thisnew Actionnull????????}

???????? privateasync void UpdateTime ()
???????? {
???????????? while (true ???????????? {
???????????????? thread// simulate time-consuming operations

???????????????? Textblock.text = DateTime. Now.tostring ();
???????????????? awaitTask. Delay (100);
????????????}
????????}
????}

When we run this program, we will find: because the main thread most of the time slice is occupied, can not timely handle system events (such as mouse, keyboard input), resulting in the program becomes very slow, even drag the window has become not smooth;

How to solve this problem, the first thing a beginner can think of is to city a thread and perform an update in the process:

???? public UserControl1 ()
???? {
???????? TextBlock = newtextBlock();
???????? this. Content = TextBlock;

???????? ThreadPool. QueueUserWorkItem (_ = = UpdateTime ());
????}

But soon it will be discovered that blocked, because WPF does not allow cross-thread access to Programs , we get a: "The calling thread cannot access this object because a different Thread owns it. " The InvalidOperationException exception

????

So how do we solve this problem? The usual practice is to put the time-consuming function in the thread pool and then cut back to the main thread to update the UI display. The preceding UpdateTime function is rewritten as follows:

???? privateasyncvoid updatetime ()
???? {
???????? while (true)
???????? {
????????????AwaitTask. Run (() = Thread. Sleep ());
???????????? Textblock.text = DateTime. Now.tostring ();
???????????? awaitTask. Delay (100);
????????}
????}

This approach will satisfy most of our needs. However, some operations are more time-consuming. For example, in a multi-window real-time monitoring, we need more than 10 dozen screens each second dozens of times of the refresh, update image This operation must be on the UI thread, and it is very time-consuming, and then back to the beginning of the situation.

It seems that this problem cannot be solved, in fact,WPF simply does not allow cross-threaded access to programs, and does not allow multithreading to update the interface . We can have a separate thread for each video surveillance window, and the update operation in that thread will not affect the main thread at this time. An article on MSDN describes the detailed operation: multithreaded ui:hostvisual. In this way, the original program is rewritten as follows:

????PrivatevoidMainwindow_loaded (ObjectSenderRoutedEventArgsE
???? {
????????HostvisualHostvisual =NewHostvisual();

????????UIElementContent =NewVisualhost(hostvisual);
????????This. Content = content;

????????ThreadThread =NewThread(NewThreadStart() =
???????? {
????????????VisualtargetVisualtarget =NewVisualtarget(hostvisual);
????????????VarControl =NewUserControl1();
???????????? Control. Arrange (NewRect(NewPoint(), content. Rendersize));
???????????? Visualtarget.rootvisual = control;

???????????? System.Windows.Threading.Dispatcher. Run ();

????????}));

???????? Thread. Setapartmentstate (ApartmentState. STA);
???????? Thread. IsBackground =True;
???????? Thread. Start ();
????}

????PublicClassVisualhost:FrameworkElement
???? {
????????VisualChild

????????PublicVisualhost (VisualChild
???????? {
????????????If(Child = =Null)
????????????????ThrowNewArgumentException("Child");

????????????This. Child = child;
???????????? Addvisualchild (child);
????????}

????????protectedoverride visual Getvisualchild (int index)
???????? {
???????????? return (index = = 0)? Child: null????????}

???????? protectedoverride int Visualchildrencount
???????? {
???????????? get {return 1;}
????????}
????}

This one is used for two new classes: Hostvisual, Visualtarget. And a visualhost of his own writing. The explanations on MSDN are not too difficult to understand, and not much to be introduced here. Finally, refactor the code and rewrite the new thread to create the control in the following way:

????PrivatevoidMainwindow_loaded (ObjectSenderRoutedEventArgsE
???? {
???????? createchildinnewthread<UserControl1> (This);
????}

????voidcreatechildinnewthread<T> (ContentControlContainer
????????whereT:UIElement,New()
???? {
????????HostvisualHostvisual =NewHostvisual();

????????UIElementContent =NewVisualhost(hostvisual);
???????? Container. Content = content;

????????ThreadThread =NewThread(NewThreadStart() =
???????? {
????????????VisualtargetVisualtarget =NewVisualtarget(hostvisual);

????????????Var control = new t???????????? Control. Arrange (newrect (new Point
???????????? Visualtarget.rootvisual = control;
???????????? System.Windows.Threading. dispatcher
????????}));

???????? Thread. Setapartmentstate (apartmentstate???????? Thread. IsBackground = true???????? Thread. Start ();
????}

Of course, I have some unnecessary restrictions on this function: The container must be contentcontrol, and the child element must be UIElement. Can be modified according to the actual needs.

Reject stuttering--use multithreading to update the UI in WPF

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.