Il est courant dans des applications n-tier d’avoir des appels SQL qui occupent le processeur et qui donnent l’impression d’un plantage de l’application où aucun message de paint ou même de click ne sera traité à temps. Et parfois un calcul assez prenant pourrait avoir le même effet.
ce petit programme vous montre comment réaliser une classe Worker qui, permet de rendre l'application fluide avec plusieurs tâches lancées en parallèle.


<Window x:Class="Background.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Background"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Content="Parallel" HorizontalAlignment="Left" Height="30" Margin="75,155,0,0" VerticalAlignment="Top" Width="70" Click="ParallelClick"/>
        <TextBox Name="tbMsg" HorizontalAlignment="Left" Height="30" Margin="290,50,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="140"/>
        <TextBox Name="tbTh1" HorizontalAlignment="Left" Height="30" Margin="290,110,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="140"/>
        <TextBox Name="tbTh2" HorizontalAlignment="Left" Height="30" Margin="290,155,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="140"/>
        <Button Name="FirstTask" Content="Tache1" HorizontalAlignment="Left" Height="30" Margin="75,190,0,0" VerticalAlignment="Top" Width="70" Click="FTClick"/>
        <Button Name="SecondTask" Content="Tache2" HorizontalAlignment="Left" Height="30" Margin="75,225,0,0" VerticalAlignment="Top" Width="70" Click="STClick"/>
        <Button Content="Cancel" HorizontalAlignment="Left" Height="30" Margin="150,225,0,0" VerticalAlignment="Top" Width="45" Click="Cancel2Click" />
        <Button Content="Cancel" HorizontalAlignment="Left" Height="30" Margin="150,190,0,0" VerticalAlignment="Top" Width="45" Click="Cancel1Click" />
        <Button Content="Cancel" HorizontalAlignment="Left" Height="30" Margin="150,155,0,0" VerticalAlignment="Top" Width="45" Click="CancelClick" />
    </Grid>
</Window>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace Background
{
    /// 
    /// Logique d'interaction pour MainWindow.xaml
    /// 
    public partial class MainWindow : Window
    {
        long i;
        Worker wk;
        Worker wk1;
        Worker wk2;
        public MainWindow()
        {
            InitializeComponent();
        }
        private void ParallelClick(object sender, RoutedEventArgs e)
        {
            wk = new Worker(DoWork, ProgressChanged, RunWorkerCompleted);
            wk.Start(sender, e);
        }
        private void FTClick(object sender, RoutedEventArgs e)
        {
            wk1 = new Worker(DoWork1, ProgressChanged1, RunWorker1Completed);
            wk1.Start(sender, e);
        }

        private void STClick(object sender, RoutedEventArgs e)
        {
            wk2 = new Worker(DoWork2, ProgressChanged2, RunWorker2Completed);
            wk2.Start(sender, e);
        }
        private void Cancel2Click(object sender, RoutedEventArgs e)
        {
            wk2.bw.CancelAsync();
        }
        private void Cancel1Click(object sender, RoutedEventArgs e)
        {
            wk1.bw.CancelAsync();
        }
        private void CancelClick(object sender, RoutedEventArgs e)
        {
            wk.bw.CancelAsync();
        }
        private void DoWork(object sender, DoWorkEventArgs e)
        {
            int i = 0;
            BackgroundWorker worker = sender as BackgroundWorker;
            for (i = 0; i < 1000; i++)
            {
                if ((worker.CancellationPending == true))
            {
                e.Cancel = true;
            }
            else
            {
                // Perform a time consuming operation and report progress.
                //Thread.Sleep(10);
                //                    Roue();//Méthodes à appeler 
                    wk.bw.ReportProgress(((int)i));
                    Thread.Sleep(10);
            }                
            }
        }
        private void DoWork1(object sender, DoWorkEventArgs e)
        {
            int i = 0;
            BackgroundWorker worker = sender as BackgroundWorker;
            for (i = 0; i < 1100; i++)
            {
                if ((worker.CancellationPending == true))
            {
                e.Cancel = true;
            }
            else
            {
                // Perform a time consuming operation and report progress.
                //Thread.Sleep(10);
                //                    Roue();//Méthodes à appeler 
                    wk1.bw.ReportProgress(((int)i));
                    Thread.Sleep(10);

                }
            }
        }
        private void DoWork2(object sender, DoWorkEventArgs e)
        {
            int i = 0;
            BackgroundWorker worker = sender as BackgroundWorker;
            for (i = 0; i < 1200; i++)
            {
                if ((worker.CancellationPending == true))
            {
                e.Cancel = true;
            }
            else
            {
                // Perform a time consuming operation and report progress.
                //Thread.Sleep(10);
                //                    Roue();//Méthodes à appeler 
                    wk2.bw.ReportProgress(((int)i));
                    Thread.Sleep(10);
            }
            }
        }
        private void RunWorker1Completed(object sender, RunWorkerCompletedEventArgs e)
        {
            if ((e.Cancelled == true))
            {
                tbTh1.Text = "Canceled!";
            }

            else if (!(e.Error == null))
            {
                tbTh1.Text = ("Error: " + e.Error.Message);
            }
            else
            {
                tbTh1.Text = "Done!";
            }
            //                obj.Cursor = null;
        }
        private void RunWorker2Completed(object sender, RunWorkerCompletedEventArgs e)
        {
            if ((e.Cancelled == true))
            {
                tbTh2.Text = "Canceled!";
            }

            else if (!(e.Error == null))
            {
                tbTh2.Text = ("Error: " + e.Error.Message);
            }
            else
            {
                tbTh2.Text = "Done!";
            }
            //                obj.Cursor = null;
        }
        private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if ((e.Cancelled == true))
            {
                tbMsg.Text = "Canceled!";
            }

            else if (!(e.Error == null))
            {
                tbMsg.Text = ("Error: " + e.Error.Message);
            }
            else
            {
                tbMsg.Text = "Done!";
            }
            //                obj.Cursor = null;
        }
        private void ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e.ProgressPercentage == -1)
            {

            }
            else
            {
                tbMsg.Text = e.ProgressPercentage.ToString();
               //                if (e.UserState.GetType() == typeof(DataParts))
               //               else
               //                    Feuille pc = (Feuille)e.UserState;
            }
        }
        private void ProgressChanged1(object sender, ProgressChangedEventArgs e)
        {
            if (e.ProgressPercentage == -1)
            {

            }
            else
            {
                tbTh1.Text = e.ProgressPercentage.ToString();
            }
        }
        private void ProgressChanged2(object sender, ProgressChangedEventArgs e)
        {
            if (e.ProgressPercentage == -1)
            {

            }
            else
            {
                tbTh2.Text = e.ProgressPercentage.ToString();
            }
        }
    }
}

 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Windows.Input;
using System.Data;
using System.Data.SqlClient;
using System.Threading;
using System.Windows.Controls;

namespace Background
{
    delegate void FWork(object sender, DoWorkEventArgs e);
    delegate void FProgress(object sender, ProgressChangedEventArgs e);
    delegate void FWCompleted(object sender, RunWorkerCompletedEventArgs e);
    class Worker
    {
        public BackgroundWorker bw = new BackgroundWorker();//backgroundworker qui anime 

        public Worker(FWork FuncWork, FProgress FuncProgress, FWCompleted FWorkCompleted)
        {
            bw.WorkerReportsProgress = true;
            bw.WorkerSupportsCancellation = true;
            bw.DoWork += new DoWorkEventHandler(FuncWork);
            bw.ProgressChanged += new ProgressChangedEventHandler(FuncProgress);
            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(FWorkCompleted);
        }
        public void Start(object sender, RoutedEventArgs e)
        {
            if (bw.IsBusy != true)
            {
                bw.RunWorkerAsync();
            }
        }
    }
}