• WPF 异步编程


    DispatherObject

    很多wpf 对象有线程相关性(thread affinity),意味在你只能在创建它的线程上使用它。这和window formUI控件一样。 WinFormcontrol.invoke() ,winform.timer 会在进行UI操作时做一个线程切换。

    wpf中,继承自System.Windows.ThreadingDispatherObject的对象都具有线程相关性, 比如:Brush, Geometry

    public class DependencyObject : DispatcherObject

    public abstract class DispatcherObject

    {

        // Fields

        private Dispatcher _dispatcher;

        // Methods

        protected DispatcherObject();

        [EditorBrowsable(EditorBrowsableState.Never)]

        public bool CheckAccess();

        [FriendAccessAllowed]

        internal void DetachFromDispatcher();

        [EditorBrowsable(EditorBrowsableState.Never)]

        public void VerifyAccess();

        // Properties

        [EditorBrowsable(EditorBrowsableState.Advanced)]

        public Dispatcher Dispatcher { get; }

    }

    CheckAccess()VeriftyAccess()来判断是否在正确的线程上,VerifyAccess会抛异常,如果不在正确的线程上。Freezable对象能够通过frozon,来消除线程的限制。

    The Dispather:

    每一个需要创建UI objects的线程必须要有一个dispatcher object.这个对象做的事相当于win32的消息泵,用一个循环不断dispatch input message to appropriate handlers.

     DispatcherObject中有这个属性,或者可以通过Dispatcher.CurrentDispather来获得当前线程的dispather.

    如果要做完一些事情后更新UI,必须保证在UI线程上更新。Dispatcher 就是提供这种功能的,Dispatcher.Invoke()方法 会等待方法执行完再返回,Dispather.Invoke()方法不会等待方法执行完,而是立即返回。Invoke()方法有死锁风险,BeginInvoke 没有。

    匿名方法:

    Public class window1:window

    {

         Public void delegate Mymethod;

         Mymethod method = delegate{ this.foreground = new SolidColorBrush(Color.Blue);}

    This.Dispather.BeginInvoke(DispatcherPriority.Normal,method);

    } //有ApplicationIdle 和SystemIdle优先级

    ;

    }

    传参数的方法:delegate void BackGround(Color c)

    Private void SetBackgroundColor(Color c) {this.background = c;}

    BackGround method = SetBackgroundColor;

    DispatcherOperation e =This.dispacher.BeginInvoke(DispatherPriority.Normal,method,Color.Blue);

    返回的 DispatherOperation.Status属性可以查看状态:

     

    DispatcherOperationStatus

    Value

    Meaning

    Pending

    The dispatcher has not yet called the method.

    Executing

    The method is currently executing on the dispatcher thread.

    Completed

    The method has finished executing.

    Aborted

    The operation was aborted.

     

    可以用DispatherOperation.Abort()退出,不要DispatherOperation.Completed+=delegate{}; 因为当加上的时候可能线程可能已经返回了。直接把完成时要做的事,放到线程执行方法中去,特别是界面处理。

     

    没有了.net异步编程的,EndInvoke()方法,也没有把一个completion callback传给BeginInvoke 方式。

     

     

    DispatcherTimer:

    WPF timer,

    private DispatcherTimer dt;

        public MyWindow( ) {

            DispatcherTimer dt = new DispatcherTimer( );

            dt.Tick += dt_Tick;

            dt.Interval = TimeSpan.FromSeconds(2);

            dt.Start( );

        }

        void dt_Tick(object sender, EventArgs e) {

            Random r = new Random( );

            byte[] vals = new byte[3];

            r.NextBytes(vals);

            Color c = Color.FromRgb(vals[0], vals[1], vals[2]);

            this.Background = new SolidColorBrush(c);

        }

    private DispatcherTimer _timer;
    timer = new DispatcherTimer(DispatcherPriority.Background);
    timer.Interval = TimeSpan.FromMinutes(5);
    timer.Tick += delegate { ScheduleUpdate(); };
    timer.Start();

    UI threaddispather

    一个Application能有多个线程来创建UI,但是一个窗口和它的element都必须在一个线程中,每一个host UI object的线程都需要一个dispatcher,让UI 对象来工作。在一个单线程的application,我们不需要创建dispather,因为application类会自动在startup时创建dispatcher,Exit时候shut down dispatcher.但是如果我们要自己建多线程UI,就得自己start upshut down Dispather.

    ThreadStart threadMethod = delegate {

        Window1 w = new Window1( );

        w.Show( );

        System.Windows.Threading.Dispatcher.Run( ); // Won't return until dispatcher shuts down

    };

    Thread thread = new Thread(threadMethod);

    thread.SetApartmentState(ApartmentState.STA);

    thread.Start( );

    继承DispatcherObject基类会在创建时自动建dispatcher实例,所以不需要new,但是要Dispatcher.Run()来使得message能够正确发送到UI object的线程中。这个方法不会返回知道dispatcher.InvokeShutdown. 对于客户自己创建的UI线程,需要手动shut down

    set the COM threading model to STA线程套间,虽然在com交互时候才用到COM threading model, 但是因为太多的系统特征需要com交互,所以dispatcher要求设置STA

     

    BackgroundWorker

    System.ComponentModel.BackgroundWorker, 这个类可以在windows formsWPF中用,但是却是两种不同的实现机制。用AsyncOperationManager来区分,一个application层的变量,当WPF application start up时候,WPF会自动配置AsyncOperationManager,(用当前dispatcher).

    WPFBackgroundWorker实际上是为了更方便使用,对dispatcher的包装。

    使用:

    1.      Attach event to DoWork event.

    2.      Add handler to ProgressChanged, RunWorkerCompleted event

    3.      为了使用progressChanged event,要设置BackgroundWorker.WorkerReportsProgress true; DoWorkhandler中,调ReportProgress()报告状态。

    例子:

    partial class MyWindow : Window {

        private BackgroundWorker bw;

        public MyWindow( ) {

            bw = new BackgroundWorker( );

            bw.DoWork += new DoWorkEventHandler(bw_DoWork);

            bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);

            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(

                                                     bw_RunWorkerCompleted);

            bw.WorkerReportsProgress = true;

            bw.RunWorkerAsync( );

        }

        void bw_DoWork(object sender, DoWorkEventArgs e) {

            // Running on a worker thread

            for (int i = 0; i < 10; ++i) {

                int percent = i * 10;

                bw.ReportProgress(percent);

                Thread.Sleep(1000);

            }

        }

        void bw_ProgressChanged(object sender, ProgressChangedEventArgs e) {

            this.Text = "Working: " + e.ProgressPercentage + "%";

        }

        void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {

            this.Text = "Finished";

        }

    当运行RunWorkerAsync( ),BackgroundWorker 在worker thread中抛出DoWork event,所以在DoWork handler中不能进行UI操作。但是ProgressChanged and RunWorkerCompleted events 是在UI threadraise的,在它们的handler中可以进行UI 操作。

    RunWorkerCompleted handler 传入RunWorkerCompletedEventArgs objectDoWork m方法中可能抛出异常,如果有异常抛出,RunWorkerCompletedEventArgs 对象会包含异常,否则为null。

  • 相关阅读:
    ie下常见的css兼容问题
    jQuery Easing 使用方法及其图解
    数组中常用的15个方法
    js按位运算符及其妙用
    图片格式知多少
    Linux top命令的用法详解
    Another app is currently holding the yum lock; waiting for it to exit...
    ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this S tatem
    Gitlab与Jenkins结合构成持续集成(CI)环境
    cobbler无人值守安装
  • 原文地址:https://www.cnblogs.com/liangouyang/p/1322624.html
Copyright © 2020-2023  润新知