به روزرسانی UI با استفاده از Dispatcher و TPL در WPF

چهارشنبه 26 خرداد 1395

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

به روزرسانی  UI با استفاده از Dispatcher  و TPL در WPF

مقدمه

برنامه های WPF بر روی اصول Thread affinity کار می کنند که به این معناست که thread هایی که بر روی این اصول نباشند نمی توانند با هم تعامل داشته باشند. به این ساختار، Single threaded apartment model می گویند. برخی اوقات برنامه نویسان نیاز دارند تا thread را مدیریت کنند و یا WPF UI را به روز رسانی کنند. اما شی WPF بر پایه ی اصول thread affinity کار می کند که از شی Dispatcher مشتق شده است.

بنابراین اگر توسعه دهندگان thread را خودشان شخصا ایجاد کنند و سپس سعی کنند تا WPF UI را به روز رسانی کنند، اصول thread affinity با استفاده از متد "VerifyAccess()" از کلاس DispatcherObject جلوی آن ها را می گیرد. و یک خطای زمان اجرا به صورت “InvalidOperationException” به آن ها نمایش می دهد.

بنابراین ما در این مقاله با استفاده از "Dispatcher" و "TPL" برنامه ی ساده ای می سازیم که در آن بتوانیم WPF UI را به روز رسانی کنیم.

فایل .XAML :

<Window x:Class="WpfApplication1.MainWindow"  
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
        Title="MainWindow" Height="350" Width="525">  
    <StackPanel>  
        <Label Name="myLabel"></Label>  
    </StackPanel>  
</Window>  

در اینجا یک label در نظر گرفته ایم. <Label Name="myLabel"></Label>

به قسمت code behind یا فایل XAML.cs بروید :

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Threading.Tasks;  
using System.Windows;  
using System.Windows.Controls;  
using System.Windows.Threading;  
  
namespace WpfApplication1  
{  
    /// <summary>  
    /// Interaction logic for MainWindow.xaml  
    /// </summary>  
    public partial class MainWindow : Window  
    {  
        public MainWindow()  
        {  
            InitializeComponent();  
            var mySource = Enumerable.Range(1, 1000).ToList();  
            Task.Factory.StartNew(() => CalculateMyOperation(mySource));  
        }  
  
        private void CalculateMyOperation(List<int> values)  
        {  
            foreach (var i in values)  
            {  
                var currentProgress = i;  
                Dispatcher.BeginInvoke(new Action(() =>  
                {  
                    myLabel.Content = "Updating..." + currentProgress;  
                }), DispatcherPriority.Background);  
            }  
        }  
    }  
}  

خروجی :

به روز رسانی ... 1

به روز رسانی...2

به روز رسانی....3

...................

به روز رسانی...100

در این برنامه از متد "BeginInvoke" همراه با Dispatcher استفاده کردیم زیرا "Dispatcher.BeginInvoke" ، زمان بندی action داده شده برای اجرای UI thread را انجام می دهد و سپس به ما اجازه می دهد تا thread جاری را با استفاده از control دوباره به جریان بیندازیم.

اما متد Invoke ، فراخوان را تا زمانی که زمان بندی به پایان برسد در حالت مسدود نگه می دارد.

اولویت dispatcher اولویت عملیات را مشخص می کند. در این برنامه ما از DispatcherPriority.Background به عنوان اولویت dispatcher استفاده می کنیم . اولویت "Background" بیان می کند که ما عملیات مورد نظرمان را بعد از اتمام همه ی عملیات non-idle انجام خواهیم داد.

ما عملیات به روز رسانی را درون یک اکشن "new Action(() =>" تعریف کرده ایم .

نتیجه گیری :

Dispatcher یک تکنیک و یا مفهوم مهم برای اجرای یک فرآیند یا عملیات است که بر روی UI thread انجام خواهد شد. در حقیقت UI به روز رسانی می شود.

 

فایل های ضمیمه

سجاد باقرزاده

نویسنده 54 مقاله در برنامه نویسان
  • WPF
  • 2k بازدید
  • 2 تشکر

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید