What is Thread?
A thread is a separate execution path within a program and Window is a multithreading operating system that manages threads. In WPF when we execute a program each program is assigned a single thread by default.
There are many benefits to use multithreading in Windows applications. Let’s see the benefits of Multithreading in Windows applications.
- Improve performance and concurrency
- Simplified coding of remote procedure calls and conversation
- Simultaneous access to multiple applications
- Reduce the number of required servers
There are also some disadvantages to use multithreading in the Window application.
- Writing a line of code is difficult
- Debugging the program is difficult
- Managing concurrency is difficult
Now, let’s start the coding part.
Step: 1
Create a Window application. And here we need to create classes for creating windows. So first create one folder and inside the folder add a class file and add the below code.
CustomDialogWindow.cs
usingSystem.ComponentModel;
usingSystem.Windows;
usingSystem.Windows.Input;
namespaceOtherThreadWindow.BaseWindow
{
publicclassCustomDialogWindow : Window, INotifyPropertyChanged
{
publiceventPropertyChangedEventHandlerPropertyChanged;
publicCustomDialogWindow()
{
this.CommandBindings.Add(newCommandBinding(SystemCommands.CloseWindowCommand, OnCloseWindow));
DataContext = this;
}
publicvoidOnPropertyChanged(stringpropertyName)
{
PropertyChanged?.Invoke(this, newPropertyChangedEventArgs(propertyName));
}
publicvirtualvoidOnDragWindow(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton != MouseButtonState.Pressed)
return;
else
{
DragMove();
}
}
publicvoidOnCloseWindow(object sender, ExecutedRoutedEventArgs e)
{
this.Close();
}
}
}
This class is used for a second dialog window.
Read More: An Overview Of Wpf Localization Extension
Step: 2
Now, we can add a class for a custom window.
CustomWindow.cs
using System;
usingSystem.Windows;
usingSystem.Windows.Input;
using Cursors = System.Windows.Input.Cursors;
usingMouseEventArgs = System.Windows.Input.MouseEventArgs;
namespaceOtherThreadWindow.BaseWindow
{
publicclassCustomWindow :CustomDialogWindow
{
private Visibility _normalizeWindowBtnVisibility;
private Visibility _maximizeWindowBtnVisibility;
public Visibility MaximizeWindowBtnVisibility
{
get{ return _maximizeWindowBtnVisibility; }
set
{
if (_maximizeWindowBtnVisibility != value)
{
_maximizeWindowBtnVisibility = value;
OnPropertyChanged(nameof(MaximizeWindowBtnVisibility));
}
}
}
public Visibility NormalizeWindowBtnVisibility
{
get{ return _normalizeWindowBtnVisibility; }
set
{
if (_normalizeWindowBtnVisibility != value)
{
_normalizeWindowBtnVisibility = value;
OnPropertyChanged(nameof(NormalizeWindowBtnVisibility));
}
}
}
publicCustomWindow()
{
this.SourceInitialized += Window_OnSourceInitialized;
this.PreviewMouseMove += Window_OnPreviewMouseMove;
}
publicvoidWindow_OnSourceInitialized(object sender, EventArgs e)
{
if (this.WindowState == WindowState.Maximized)
{
MaximizeWindowBtnVisibility = Visibility.Collapsed;
NormalizeWindowBtnVisibility = Visibility.Visible;
}
elseif (this.WindowState == WindowState.Normal)
{
MaximizeWindowBtnVisibility = Visibility.Visible;
NormalizeWindowBtnVisibility = Visibility.Collapsed;
}
}
publicvoidWindow_OnPreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton != MouseButtonState.Pressed)
Cursor = Cursors.Arrow;
}
publicoverridevoidOnDragWindow(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 2)
return;
if (e.LeftButton != MouseButtonState.Pressed)
return;
{
DragMove();
}
}
publicvoidButtonMinimize_OnClick(object sender, RoutedEventArgs e)
{
WindowState = WindowState.Minimized;
}
publicvoidButtonMaximize_OnClick(object sender, RoutedEventArgs e)
{
WindowState = WindowState.Maximized;
ShowRestoreDownButton();
}
publicvoidShowRestoreDownButton()
{
MaximizeWindowBtnVisibility = Visibility.Collapsed;
NormalizeWindowBtnVisibility = Visibility.Visible;
}
publicvoidShowMaximumWindowButton()
{
NormalizeWindowBtnVisibility = Visibility.Collapsed;
MaximizeWindowBtnVisibility = Visibility.Visible;
}
publicvoidButtonRestoreDown_OnClick(object sender, RoutedEventArgs e)
{
ShowMaximumWindowButton();
}
privatevoidSwitchState()
{
switch (WindowState)
{
caseWindowState.Normal:
{
WindowState = WindowState.Maximized;
ShowRestoreDownButton();
break;
}
caseWindowState.Maximized:
{
ShowMaximumWindowButton();
break;
}
}
}
publicvoidButton_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if ((ResizeMode == ResizeMode.CanResize) ||
(ResizeMode == ResizeMode.CanResizeWithGrip))
{
SwitchState();
return;
}
}
~CustomWindow()
{
this.SourceInitialized -= Window_OnSourceInitialized;
this.PreviewMouseMove -= Window_OnPreviewMouseMove;
}
}
}
Step: 3
OtherthreadwindowBase.cs
using System;
usingSystem.Runtime.InteropServices;
usingSystem.Windows;
usingSystem.Windows.Interop;
namespaceOtherThreadWindow.BaseWindow
{
publicclassOtherThreadWindowBase : Window, IDisposable
{
publicvoidDispose()
{
try
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
catch (Exception ex)
{
}
}
}
}
One Stop Solution for WPF Application Development ?
Your Search ends here.
Step: 4
Now, we can write a code for animation. For this, you need to add one content page. On the page add the below code. And add one GIF in the resources folder.
EkgWindow.xamlHere, we can add GIF for animation. And inherit base class on code-behind.
EkgWindow.xaml.cs
public partial classEkgController :OtherThreadWindowBase
{
publicEkgController() : base()
{
InitializeComponent();
}
}
Step: 5
After adding GIF, create a class to add their start time, height, width, etc. using the below code.
EkgManager.cs
using System;
usingSystem.Collections.Generic;
usingSystem.Threading;
usingSystem.Windows.Threading;
namespaceOtherThreadWindow.EkgWindow
{
internalclassEkgManager
{
privatebool _isStarting;
internalEkgManager(Dictionary settings, boolisStarting)
{
_isStarting = isStarting;
MakeEkgOnDifferentThread();
}
internalvoidMakeEkgOnDifferentThread()
{
try
{
Thread newWindowThread = newThread(newThreadStart(ThreadStartingPoint));
newWindowThread.SetApartmentState(ApartmentState.STA);
newWindowThread.IsBackground = true;
newWindowThread.Start();
}
catch (Exception ex)
{
}
}
privatevoidThreadStartingPoint()
{
try
{
if (_isStarting)
{
Thread.Sleep(1900);
MainWindow.Current.Dispatcher.Invoke(() =>
{
MainWindow.Current.Topmost = true;
MainWindow.Current.Topmost = false;
MainWindow.Current.Activate();
});
_isStarting = false;
}
System.Windows.Threading.Dispatcher.Run();
}
catch (Exception ex)
{
}
}
internalvoidWindowSettingsChanged()
{
}
internalvoidKillEkg()
{
}
internalvoidWindowActivated()
{
if (_isStarting) return;
}
}
}
Step: 6
Now, open MainWindow.XAML and create a design for the main page.
MainWindow.XAML
Step: 7
Open MainWindow.XAML.cs file and add the below code.
MainWindow.xaml.cs
usingOtherThreadWindow.BaseWindow;
usingOtherThreadWindow.EkgWindow;
using System;
usingSystem.Collections.Generic;
usingSystem.Threading;
usingSystem.Threading.Tasks;
usingSystem.Windows;
usingSystem.Windows.Forms;
namespaceOtherThreadWindow
{
publicpartialclassMainWindow :CustomWindow
{
publicMainWindow()
{
Current = this;
InitializeComponent();
LocationChanged += WindowLocationChangedHandler;
}
privatevoidWindowLocationChangedHandler(object sender, EventArgs e)
{
GetEkgSettings();
}
publicstaticMainWindow Current { get; set; }
privatevoidButton_Click(object sender, RoutedEventArgs e)
{
vardialogWindow = newDialogWindow();
dialogWindow.Width = 900;
dialogWindow.Height = 600;
dialogWindow.Owner = this;
dialogWindow.Title = "Custom Dialog Window Title";
dialogWindow.ShowDialog();
{
}
}
privatevoidGetEkgSettings()
{
}
internalstaticdoubleGetWindowsScalingWidth()
{
returnScreen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth;
}
internalstaticdoubleGetWindowsScalingHeight()
{
returnScreen.PrimaryScreen.Bounds.Height / SystemParameters.PrimaryScreenHeight;
}
privatevoidMainWindoLoaded(object sender, RoutedEventArgs e)
{
}
privatevoidMainRootActivated(object sender, EventArgs e)
{
}
privatevoidMainRootStateChanged(object sender, EventArgs e)
{
}
privatevoidMakeYourMainWindowBusy(object sender, RoutedEventArgs e)
{
Thread.Sleep(5000);
}
~MainWindow()
{
LocationChanged -= WindowLocationChangedHandler;
}
}
}
Step: 8
Now, we can create one more content page for when we click the main window that will be open the second window.
DialogWindow.XAML
Step: 9
Open DialogWindow.xaml.cs and inherit CustomDialogWindow.cs file.
DialogWindow.xaml.cs
usingOtherThreadWindow.BaseWindow;
namespaceOtherThreadWindow
{
publicpartialclassDialogWindow :CustomDialogWindow
{
publicDialogWindow()
{
InitializeComponent();
}
}
}
Output:
Conclusion
In this blog, we have acquired a basic understanding of threads, their advantages and disadvantages, and their process. Using thread, we can maintain a responsive user interface.