Threading Model IN WPF ------------ Consolidated from MSDN

No matter how well architected, no UI framework will ever be able to provide a single threaded solution for every sort of problem. WPF comes close, but there are still situations where multiple threads improve user interface (UI) responsiveness or application performance. After discussing some background material, this paper will explore some of these situations. We’ll finish with a discussion of some lower level details for the particularly curious.

Overview and the Disptacher
Typical, WPF applications start their lives with two threads: one for handling rendering and another for managing the UI. The rendering thread effectively runs hidden in the background while the UI thread receives input, handles events, paints the screen, and runs application code. Most applications use a single UI thread, although in some situations it is best to use several. We’ll discuss this with an example later in the paper.

The UI thread queues work items inside an object called a Dispatcher. The Dispatcher selects work items on a priority basis and runs each one to completion. Every UI thread must have at least one Dispatcher and each Dispatcher can execute work items in exactly one thread.

The trick to building responsive, friendly applications is to maximize the Dispatcher throughput by keeping the work items small. This way items never get stale sitting in the Dispatcher queue waiting for processing. Any perceivable delay between input and response can frustrate a user.

How then are WPF applications supposed to handle big operations? What if my code involves a large calculation or needs to query a database on some remote server? Usually, the answer is to handle the big operation in a separate thread, leaving the UI thread free to tend to items in the Dispatcher queue. When the big operation completes, it can report its result back to the UI thread for display.

Historically, Windows only allows UI elements to be accessed by the thread that created them. This means that a background thread in charge of some long running task can’t update a textbox when it’s done. Windows does this to ensure the integrity of UI components. A listbox could turn out looking very strange if its contents were updated by a background thread during painting.

WPF has a built in mutual exclusion mechanism that enforces this. Just about every class in WPF descends from DisptcherObject. At construction, a DisptcherObject stores a reference to the Dispatcher linked to the currently running thread. In effect, the DisptcherObject associates with the thread that creates it. During program execution, a DisptcherObject can call its public VerifyAccess method. VerifyAccess examines the Dispatcher associated with the current thread and compares it to the Dispatcher reference stored during construction. If they don’t match, VerifyAccess throws an exception. VerifyAccess is intended to be called at the beginning of every method belonging to a DisptcherObject.

If only one thread can modify the UI how do background threads interact with the user? A background thread can ask the UI thread to perform an operation on its behalf. It does this by registering a work item with the Dispatcher of the UI thread. The Dispatcher class provides two methods for registering work items: Invoke and BeginInvoke. Both methods schedule a delegate for execution. Invoke is a synchronous call – that is, it doesn’t return until the UI thread actually finishes executing the delegate. BeginInvoke is asynchronous and returns immediately.

the Dispatcher orders the elements in its queue by priority. There are ten levels that may be specified when adding an element to the Dispatcher queue. These priorities are maintained in the DispatcherPriority enumeration. Detailed information about DispatcherPriority levels can be found in the Windows SDK documentation. 

Example:

XAML

< Grid >
        
< Grid .RowDefinitions >
            
< RowDefinition  Height ="50" />
            
< RowDefinition  Height ="50" />
        
</ Grid.RowDefinitions >
    
< ProgressBar  Margin ="120,12,99,15"  Name ="progressBar1"  Value ="100"   />
    
< Button  Grid.Row ="1"  Margin ="147,17,155,10"  Name ="button1"  Click ="button1_Click" > Button </ Button >
  
</ Grid >

CS 

public   partial   class  Window1 : System.Windows.Window
    
{
        
public delegate void AscCall();

        
public Window1()
        
{
            InitializeComponent();
        }


        
void button1_Click(object sender, RoutedEventArgs e)
        
{
            
/* The first way of AscCall */
            AscCall acall 
= new AscCall(DoLargeBlock);
            acall.BeginInvoke(
nullnull);

            
/* The second way of AscCall */
            
//ThreadStart ts = new ThreadStart(DoLargeBlock);
            
//Thread td = new Thread(ts);
            
//td.Start();
        }


        
private void DoLargeBlock()
        
{
            System.Threading.Thread.Sleep(
5000);
            UpdateUI();
        }


        
private void UpdateUI()
        
{
            progressBar1.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
                
new AscCall(UpdatePrograbass));
            button1.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
                
new AscCall(UpdateButton));
        }


        
private void UpdatePrograbass()
        
{
            progressBar1.Value 
= 50;
        }


        
private void UpdateButton()
        
{
            
this.button1.Content = "Done";
        }

    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值