WPF开发dll时,关于STA线程问题的总结(文章过期,请看另一篇!!)

问题起因:调用线程必须为STA,因为许多UI组件都需要

查找资料:

方案1: 

Thread t = new Thread(new ThreadStart(delegate{

///do something

}));
            t.SetApartmentState(ApartmentState.STA);
            t.IsBackground = true;

方案2:window.Dispatcher.Invoke(new Action(delegate{

}));

因为wpf作为的是类库。所有的窗体都没有初始化,谈毛的方案2啊。

方案1 可以在委托中处理窗体。但是有个坑,外部每次调用都会重新new线程,在线程保证执行完成的情况下,依然会有内存泄露的情况,不论怎么搞都会泄露。

结论:window.Dispatcher.Invoke 不会泄露内存,但是没有一个主窗体供调用。ApartmentState.STA 能调用,但是内存泄露。

最终解决方案:将方案1和方案2 整合到一起,解决内存泄露问题。

思路:初始化一个STA线程作为全局变量。线程的委托方法 内部是个死循环+线程阻塞。通过控制参数达到控制 STA线程内部的运行。

代码:

    public  class UIThread
    {

        //是否同步
        private bool Async { get; set; }

        //窗体要加载的数据
        private JObject Msg { get; set;}

        //要调用的窗体名称

        private string WinName { get; set; }

        public void Dispatch(string winName,JObject msg)
        {
            Init();
            this.Msg = msg;
            this.WinName = winName;
            this.Async = true;

          //唤醒子线程
            areA.Set();

         //让主线程等待
            areB.WaitOne();
        }

  //主线线程和子线程同步用到的两个东东,不晓得是个什么鬼

  private static AutoResetEvent areA = new AutoResetEvent(false);
  private static AutoResetEvent areB = new AutoResetEvent(false);

//委托方法,将当前对象传进来

  private void Invoke(object obj)
        {
            UIThread p = (UIThread)obj;

        //创建主窗体,主要是想调用它的Dispatcher.Invoke
            Window win = new Window();

        //死循环,让线程一直存活

             while (true)
            {

                //等待主线程唤醒

                areA.WaitOne();

               win.Dispatcher.Invoke(new Action(delegate {

                               ///调用UI,乱写的,懂那个意思就行

                                TestWin tw = new TestWin(p.Msg,p.winName);

                                tw.ShowDialog();

                                //子线程运行完成,唤醒主线程

                                areB.Set();

                        //继续执行到areA.WaitOne();停止,等待唤醒

                        }));

                }

        }

        //STA线程是否初始化

        private bool b;

        //初始化STA线程
        private void Init()
        {
            if (b) return;
            b = true;

              //不晓得是个什么卵
            ParameterizedThreadStart pst = new ParameterizedThreadStart(Invoke);
            Thread t = new Thread(pst);
            t.SetApartmentState(ApartmentState.STA);
            t.IsBackground = true;

             //当前对象作为参数,干进来
            t.Start(this);
        }

}

调用:先干个全局变量

public static UIThread uit = new UIThread();

走起:

uit.Dispatch(winName, result);

缺点:不能并发,不然扯到蛋!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值