Original: Dispatcher.begininvoke () Analysis of causes of UI interface deadlock caused by improper use of methods
Some time ago, a company colleague developed a gadget that, during the execution of the tool, theUI interface was stuck in a state of deadlock.
by reading Code discovery, the main reason is that Improper use of the Dispatcher.begininvoke () method.
This article uses a WPF simulation program to demonstrate the phenomenon of interface deadlock and to modify the code to solve the problem of the interface card dead.
I hope that through the study of this article, we can have a new understanding of the Dispatcher.begininvoke () method.
The article begins by giving an example code that the interface dies directly.
Sample WPF program, used to calculate 1~n and values, where n can be 1 billion ~25 A value between billion, through the interface input, the result is displayed in the text box behind the N input box, since it is a WPF Program, the code contains XAML and CS the two parts of the code are given in this paper.
The following is the CS code:
using System;
using System.Windows;
using System.Threading;
namespace DispatcherExample
{
/// <summary>
/// Interactive logic of MainWindow.xaml
/// </summary>
public partial class MainWindow: Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
Int64 inputNumber;
if (!Int64.TryParse(this.textBox1.Text, out inputNumber))
{
MessageBox.Show("Please enter the integer data between 100 million and 1 billion!");
return;
}
if (inputNumber> 2500000000 || inputNumber<100000000)
{
MessageBox.Show("Please enter integer data between 100 million and 1 billion!");
return;
}
Thread newThread = new Thread(new ParameterizedThreadStart(GetResult));
newThread.Start(inputNumber);
}
private void GetResult(object inputNumber)
{
this.Dispatcher.BeginInvoke((Action)delegate()
{
this.textBox2.Text = CalcSum((Int64)inputNumber).ToString();
});
}
private double CalcSum(Int64 inputNumber)
{
double sum=0;
for (int i = 0; i <inputNumber; i++)
{
sum +=i;
}
return sum;
}
}
}
The following is the XAML code:
<Window x:Class="DispatcherExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Seeking (and) you billions of times~~" Height="350" Width="525" ResizeMode="NoResize">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="252*" />
<ColumnDefinition Width="251*" />
</Grid.ColumnDefinitions>
<Button Content="Calculation and value" Height="23" HorizontalAlignment="Left" Margin="213,168,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" Grid. ColumnSpan="2" />
<Label Content="Enter a number between 100 million and 2.5 billion:" Height="28" HorizontalAlignment="Left" Margin="36,93,0,0" Name="label1" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="158,96,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Grid.ColumnSpan="2" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="35,96,0,0" Name="textBox2" VerticalAlignment="Top" Width="177" Text="The result is here..." Grid. Column="1" />
</Grid>
</Window>
Execute the program, the interface is as follows:
Enter 2500000000, click "Calculate and Value" button, the program starts calculation and value, the interface card is dead, can no longer operate the program (such as moving position or re-entry, etc.).
Analyze the code and find that the problem should be in the following code, because there is an operation that invokes the main thread of the UI in that part of the code, which often causes the interface to die.
private void GetResult(object inputNumber)
{
this.Dispatcher.BeginInvoke((Action)delegate()
{
this.textBox2.Text = CalcSum((Int64)inputNumber).ToString();
});
}
So, where does the problem really go?
To figure this out, you need to know the Dispatcher.begininvoke () method.
on MSDN on The Dispatcher.begininvoke method is interpreted as follows :
Dispatcher. BeginInvoke Method (Action)
Executes the specified delegate asynchronously on the thread associated with the Dispatcher.
So what is the thread associated with Dispatcher in this example ?
It's easy to figure this out. Just know this. The This in Dispatcher.begininvoke () refers to what is right. In Visual Studio, in the case of this, find this refers to the current form class (such as), which is the main thread of the program.
Here, we should know where the problem is.
The reason: in the GetResult () method, the sum operation is given to the main thread to complete, when the calculation is not completed, the interface will naturally be stuck.
By talking to a colleague, what he really wants is to open a new thread to complete his intended operation (similar to the sum in the sample program), and then call the main thread to display the result after the result is out.
The interface does not appear to be stuck, but the above code does not achieve the desired result.
The reason is already explained, because this code will still throw the sum of the calculation to the main thread, although the new thread, but the new threads do not do the sum operation, it can be said around a circle and back.
The main thread opens new threads, and new threads call the main thread. It's kind of like a buck at work, I give you one thing, you say no, and kick back to me.
It is easy to find the reason and then modify the code as follows:
private void GetResult(object inputNumber)
{
double result=CalcSum((Int64)inputNumber);
this.Dispatcher.BeginInvoke((Action)delegate()
{
//this.textBox2.Text = CalcSum((Int64)inputNumber).ToString();
this.textBox2.Text = result.ToString();
});
}
As for why this modification, I think: you understand.
Execute the program again, enter 2500000000, SUM, the interface no longer has a deadlock phenomenon.
That's it, I'm going to go to sago.
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Dispatcher.begininvoke () Analysis of causes of UI interface deadlock due to improper use of the method