首页 新闻 会员 周边

调用线程无法访问此对象,因为另一个线程拥有该对象

0
悬赏园豆:50 [已关闭问题] 关闭于 2017-01-03 12:57

先说下背景,程序启动时,用一个线程跑登录窗口页面,主线程继续运行,当登录窗结束时执行Application.Current.MainWindow.Show();显示主页面。此时不报错!

报错的场景:当密码过期时,再子线程内弹出一个修改密码页面,修改完成后登录窗结束继续执行Application.Current.MainWindow.Show();时就报错了,报错内容:调用线程无法访问此对象,因为另一个线程拥有该对象,但是明明这句话是在主线程的程序里写的,不知道怎么就被占用了,尝试了:

Application.Current.MainWindow.Dispatcher.Invoke(new Action(() =>
                {
                    Application.Current.MainWindow.Show();
                }));

还是同一个错误;

又尝试 去掉子线程弹出修改密码页面发现不报错,原因就是出在子线程又弹出页面了么?求大神解惑,五十豆不成敬意

问题补充:

主程序的代码,子线程登录界面

 // 使用登陆线程显示登陆窗口                

var loginThread = new System.Threading.Thread(() =>                 {                    

       var login = App.LoginView = new LoginView();                                               login.Show();

                    // 允许主线程继续执行   

                  Mre.Set();

                    login.Closed += (s, arg) => login.Dispatcher.BeginInvokeShutdown(System.Windows.Threading.DispatcherPriority.Background);                     System.Windows.Threading.Dispatcher.Run();                    

Mre.Set();                   

  // 当以非正常方式(如Alt+F4)关闭登陆窗口时,Result属性还没有进行设置,此时将设置为false等同于点击退出按钮关闭     

                if (login.Result == null)        

             {                         login.Result = false;                     }  

               });         

        loginThread.SetApartmentState(System.Threading.ApartmentState.STA);                 loginThread.Start();              

   // 等待登陆线程完成实例创建的操作             

    Mre.WaitOne();                

Mre.Reset();                

 new Bootstrapper().Run();

登录界面 登录成功之后  就是这个判断里面 如果 不ShowDialog这个页面  就不会报错,show了之后 就是标题那种错误

//判断用户密码是否过期
                    if(密码过期)
                    {
                        ChangePW cp = new ChangePW(pwdPassword.Password);
                        cp.Owner = this;
                        cp.ShowDialog();
                     
                    }

 

 

最后WPF客户端宿主启动程序,Bootstrapper类 等待登录结束之后 show主页面 具体错的位置是标红的

protected override void InitializeModules()        

{             base.InitializeModules();

            App.Mre.WaitOne();          

   if (App.LoginView.Result == true)          

   {                                           

   Application.Current.MainWindow.Show(); 

       }            

else             {                 App.Current.Shutdown();             }

狂狗A地板的主页 狂狗A地板 | 初学一级 | 园豆:121
提问于:2016-11-08 11:35
< >
分享
所有回答(3)
0

多线程之间,主线程的控制等等是被保护的

 

在新建的子线程中

this.Invoke(new Action(() =>
{
Application.Current.MainWindow.Show();
}));

盟怀部孩 | 园豆:878 (小虾三级) | 2016-11-08 14:42

用this即可

支持(0) 反对(0) 盟怀部孩 | 园豆:878 (小虾三级) | 2016-11-08 14:42

主要是我这句Application.Current.MainWindow.Show(); 是在主线程的代码里写的, 子线程执行的时候,不知道为什么弹出一个window之后就让这个子线程占用了Application.Current.MainWindow这个资源,如果子线程不弹出那个window是不报错的,我试试新建一个子线程

支持(0) 反对(0) 狂狗A地板 | 园豆:121 (初学一级) | 2016-11-08 15:07

@狂狗A地板: 我当时用winform的时候,this.Invoke可以在多线程上面随意操作主线程新建的对象。wpf就不清楚了,this.Invoke没办法解决吗?

支持(0) 反对(0) 盟怀部孩 | 园豆:878 (小虾三级) | 2016-11-08 15:23

wpf是.Dispatcher.Invoke 按说是可以解决的,但是这个太操蛋了,对这个错误就是解决不了

支持(0) 反对(0) 狂狗A地板 | 园豆:121 (初学一级) | 2016-11-08 15:26

@狂狗A地板: WPF是 this.Dispatcher.Invoke

用BeginInvoke

this.Dispatcher.BeginInvoke(new UpdateForm_dl(UpdateForm), new object[] { "我是文本框", "haha" });

支持(0) 反对(0) 盟怀部孩 | 园豆:878 (小虾三级) | 2016-11-08 15:29
0

你把你代码贴出来吧。你这一点点的挤谁知道什么情况。

Daniel Cai | 园豆:10424 (专家六级) | 2016-11-08 15:09

代码太多,主要的贴出来了有点乱,麻烦大哥瞄一眼

支持(0) 反对(0) 狂狗A地板 | 园豆:121 (初学一级) | 2016-11-08 15:25
0

再原有主程序页面实现这个功能 不放在子线程执行了

狂狗A地板 | 园豆:121 (初学一级) | 2017-01-03 11:37
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册