چگونه میتوانیم از Threads در WPF استفاده کنیم

Threads در WPF

مقوله ی Threads در WPF به یک برنامه اجازه می دهد که چند پردازش را به تور همزمان انجام دهد بنابراین می تواند بیش از یک عمل در زمان انجام دهد. Window Presentation Foundation (WPF) به توری طراحی شده است که به developer در سختی های threading بسیار کمک می کند. در این مقاله بیشتر با threading آشنا می شوید.

Threads در WPF

همه ی اپلیکیشن های WPF با حداقل یکی از دو threads زیر اجرا می شوند.

For rendering: در background (پشت زمینه) اجرا می شود و مخفی می ماند.

For managing UI interface (UI thread): اکثر object های WPF با UI thread گره خورده اند. که input (ورودی)، paints the screen (رنگ صفحه نمایش)، runs code و handles events (دسته حوادث) را دریافت می کند.

WPF از مدل single-threaded apartment پشتیبانی می کند که قانون های زیر را دارد:

یک thread در کل اپ اجرا می شود و مالکیت همه ی object های WPF را بر عهده می گیرد.

المان های WPF، thread affinity دارند، به عبارت دیگر thread ها نمی توانند با یک دیگر تعامل بر قرار کنند.

Object های WPF که thread affinity دارند، از یک Object Dispatcher مشتق می گیرند.

Thread handling در WPF توسط برنامه نویس

زمانی که یک اپ در WPF ایجاد می کنید، بعضی اوقات برنامه نویس باید thread ها را مدیریت کند، که بنابر این چند راه برای حل و استفاده از thread در اپ فراهم می کند. در زیر دو روش handling thread ها آمده است.

The Dispatcher (توزیع)

The Background Worker

The Dispatcher

The Dispatcher نمونه ای از کلاس System.Windows.Threading.Dispatcher می باشد. که application thread و مدیریت یک صف از کارها بر عهده ان می باشد. که عملیات UI را با اولویت و به روش First in First Out (اولین ورودی اولین خروجی- FIFO) اجرا می کند. آن یک thread جدید نمی سازد و به صورت multi-threaded نیست.

هر object، Visual WPF از یک DispatcherObject مشتق می گیرد. و یک object به کلاس DispatcherObject متصل می شود.

در زیر عضو های کلاس DispatcherObject آمده است.

Properties

Dispatcher: یک Dispatcher می گیرد.

Methods

متود های زیادی در کلاس DispatcherObject وجود دارد. متود های مهم در زیر معرفی شده اند:

CheckAccess: اگر کد یک thread باشد که بتواند از object استفاده کند true می دهد.

VerifyAccess: اگر کد در thread درست برای استفاده از object باشد هیچ کاری انجام نمی دهد در غیر این صورت یک InvalidOperationException می دهد.

GetType: نوع نمونه فعلی را می گیرد.

Object های WPF برای project کردن خود از VerifyAccess استفاده می کنند.

دلایل استفاده از Dispatcher

مثال:

using System;  
  
using System.Threading;  
  
using System.Windows;  
  
namespace WpfApplication1  
{  
  
    /// <summary>    
  
    /// Interaction logic for WPF UI Upadation using    
  
    /// thread.    
  
    /// </summary>    
  
    public partial class MainWindow : Window  
    {  
  
        public MainWindow()  
        {  
  
            InitializeComponent();  
  
        }  
  
        private void MyButton_Click(object sender, RoutedEventArgs e)  
        {  
  
            Thread thread = new Thread(UpdateText);  
  
            thread.Start();  
  
  
        }  
  
        private void UpdateText()  
        {  
  
            Thread.Sleep(TimeSpan.FromSeconds(5));  
  
            TxtName.Text = "Hello Geeks !";  
  
        }  
  
    }  
  
}  

این کد صحیح نمی باشد چرا که متود UpdateText روی یک thread جدید اجرا می شود و آن thread اجازه دسترسی به object های WPF را ندارد.

کد صحیح:

using System;  
  
using System.Threading;  
  
using System.Windows;  
  
namespace WpfApplication1  
{  
  
    /// <summary>    
  
    /// Interaction logic for WPF UI Upadation using    
  
    /// Dispatcher.    
  
    /// </summary>    
  
    public partial class MainWindow : Window  
    {  
  
        public MainWindow()  
        {  
  
            InitializeComponent();  
  
        }  
  
        private void MyButton_Click(object sender, RoutedEventArgs e)  
        {  
  
            Thread thread = new Thread(UpdateText);  
  
            thread.Start();  
  
            ;  
  
        }  
  
        private void UpdateText()  
        {  
  
            Thread.Sleep(TimeSpan.FromSeconds(5));  
  
            this.Dispatcher.BeginInvoke(new Action(() =>  
            {  
  
                TxtName.Text = "Hello Geeks !";  
  
            }));  
  
        }  
  
    }  
  
}  

بنابراین Dispatcher بهترین راه برای بروز رسانی WPF UI با thread می باشد.

The Background Worker

در کار های وقت گیر خیلی به کار می آید و موثر می باشد. کد را همزمان اجرا می کند. در یک thread جداگانه استناد می شود. به صورت خودکار با thread اصلی اپ همزمان می شود.

برای اجرای یک عمل در background استفاده می شود و اجرای UI را بر عهده می گیرد. مواردی که در آنها می توان از Background worker استفاده کرد در زیر آمده اند:

اگر کاربر یک UI پاسخگو (responsive) و faces delays در یک عمل به خصوص بخواهد.

دانلود داده ها (Data download)

معاملات پایگاه داده (Database transactions)

ackgroundWorker یک کلاس زیر گروه System.ComponentModel می باشد. عملیات را در یک thread جدا اجرا می کند.

using System;  
  
using System.ComponentModel;  
  
using System.Threading;  
  
namespace BackGroundWorkerExample  
{  
  
    /// <summary>    
  
    /// It implements backgroundworker.    
  
    /// </summary>    
  
    class Program  
    {  
  
        private static BackgroundWorker backgroundWorker;  
  
        static void Main(string[] args)  
        {  
  
            backgroundWorker = new BackgroundWorker  
  
            {  
  
                WorkerReportsProgress = true,  
  
                WorkerSupportsCancellation = true  
  
            };  
  
            //Event creation.    
  
            //For the performing operation in the background.    
  
            backgroundWorker.DoWork += backgroundWorker_DoWork;  
  
            //For the display of operation progress to UI.    
  
            backgroundWorker.ProgressChanged += backgroundWorker_ProgressChanged;  
  
            //After the completation of operation.    
  
            backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;  
  
            backgroundWorker.RunWorkerAsync("Press Enter in the next 5 seconds to Cancel operation:");  
  
            Console.ReadLine();  
  
            if (backgroundWorker.IsBusy)  
            {  
  
                backgroundWorker.CancelAsync();  
  
                Console.ReadLine();  
  
            }  
  
        }  
  
        /// <summary>    
  
        /// Performs operation in the background.    
  
        /// </summary>    
  
        /// <param name="sender"></param>    
  
        /// <param name="e"></param>    
  
        static void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)  
        {  
  
            for (int i = 0; i < 200; i++)  
            {  
  
                if (backgroundWorker.CancellationPending)  
                {  
  
                    e.Cancel = true;  
  
                    return;  
  
                }  
  
                backgroundWorker.ReportProgress(i);  
  
                Thread.Sleep(1000);  
  
                e.Result = 1000;  
  
            }  
  
        }  
  
        /// <summary>    
  
        /// Displays Progress changes to UI .    
  
        /// </summary>    
  
        /// <param name="sender"></param>    
  
        /// <param name="e"></param>    
  
        static void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)  
        {  
  
            Console.WriteLine("Completed" + e.ProgressPercentage + "%");  
  
        }  
  
        /// <summary>    
  
        /// Displays result of background performing operation.    
  
        /// </summary>    
  
        /// <param name="sender"></param>    
  
        /// <param name="e"></param>    
  
        static void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)  
        {  
  
            if (e.Cancelled)  
            {  
  
                Console.WriteLine("Operation Cancelled");  
  
            }  
  
            else if (e.Error != null)  
            {  
  
                Console.WriteLine("Error in Process :" + e.Error);  
  
            }  
  
            else  
            {  
  
                Console.WriteLine("Operation Completed :" + e.Result);  
  
            }  
  
        }  
  
    }  
  
}  

خروجی:

Threads در WPF

تفاوت های بین Dispatcher و Background Worker

Backgrounds Worker کد ها را به صورت همزمان اجرا می کند و آنها را در یک thread جدا استناد می کند. به صورت خودکار با thread اصلی اپ همزمان می شود در حالی که Dispatcher یک لیست از کار هایی که باید انجام شوند را پردازش می کند.

Backgrounds Worker در thread های جدا اجرا می شود در صورتی که dispatcher با UI thread، یک اپلیکیشن WPF اجرا می شود.

اگر می خواهید یک عملیات را در background، UI انجام دهید از background worker استفاده کنید و از Dispatcher برای بروز رسانی WPF UI.

 موفق باشید!

داریوش فرخی

داریوش فرخی هستم از سال 92 شروع به یادگیری برنامه نویسی و از سال 93 در بخش برنامه نویسی و تولید محتوای سایت mspsoft.com مشغول هستم. فعالیتم نیز بیشتر در زمینه های برنامه نویسی با سی شارپ و asp.net بوده است. اوقات فراغتم را هم غالبا با تماشای فیلم یا بازی های کامپیوتری پر میکنم .

نوشته‌های مرتبط

دیدگاه‌ها

*
*

این سایت از اکیسمت برای کاهش هرزنامه استفاده می کند. بیاموزید که چگونه اطلاعات دیدگاه های شما پردازش می‌شوند.

    amin پاسخ

    اموزش جالبی بود
    تشکر :)

ما یک پرسشنامه‌ی کوچولو داریم، که قول میدیم وقتتون رو خیلی نمی‌گیره، ولی کلی به ما کمک می‌کنه، چون هم assessment مونه ,و هم شما به ما در این زمینه کمک میکنید.بزن بریم