C# 多线程无法访问此。关闭()

C# 多线程无法访问此。关闭(),c#,wpf,multithreading,splash-screen,opentk,C#,Wpf,Multithreading,Splash Screen,Opentk,因此,我知道您只能从创建UI控件的线程访问它,但我收到一个错误,抱怨行“this.Close”。我试图做的是启动一个线程,用OpenTK动画打开一个启动屏幕 错误:调用线程无法访问此对象,因为其他线程拥有它 代码如下: public MainWindow() { InitializeComponent(); closeSplashBool = false; Thread t = new Thre

因此,我知道您只能从创建UI控件的线程访问它,但我收到一个错误,抱怨行“this.Close”。我试图做的是启动一个线程,用OpenTK动画打开一个启动屏幕

错误:调用线程无法访问此对象,因为其他线程拥有它

代码如下:

  public MainWindow()
    {

        InitializeComponent();

          closeSplashBool = false;              

          Thread t = new Thread(() =>
              {
                  openSplash = new SplashScreen();
                  openSplash.Show();

              }
                  );
          t.SetApartmentState(ApartmentState.STA);
          t.Start(); 

    ///
    /// Long running task
    ///

    closeSplashBool = true;
    }
SplashScreen构造函数中唯一的一行代码是InitializeComponents。下面是SplashScreen类的动画函数,用于控制何时关闭SplashScreen:

        private void splashControl_Paint(object sender, PaintEventArgs e)
    {
        //make sure our GL control has loaded
        if (!loaded)
            return;



        if (animCount <= 0 )
        {
            Thread.Sleep(200);
            if (MainWindow.closeSplash)
                this.Close();  //program crashes on this line
        }
        else if (animCount < 3.75 && animCount >=2.75)
        {
            animCount -= .2f;
            System.Threading.Thread.Sleep(1);
        }
        else if (animCount < 2.75)
        {
            animCount -= .07f;
            System.Threading.Thread.Sleep(5);
        }
        else 
        {
            animCount -= .7f;
            System.Threading.Thread.Sleep(1);
            if (animCount < 0)
                animCount = 0;
        }
        Render();
    }
我在线程“t”中创建了一个“新”启动屏幕,因此我认为调用“this.Close”不会有任何访问冲突。我的问题是为什么我会受到这种访问违规?我曾尝试根据其他人的建议将“this.close”替换为“Dispatcher.InvokeShutdown”,但随后闪屏从未消失

参见MSDN


有没有理由不使用内置WPF框架来显示初始屏幕,只需向VS项目添加一个“新项目”->“初始屏幕WPF”?不要创建多个UI线程。你只是自找麻烦。在第一个UI线程中执行非UI工作时,不要创建第二个UI线程来显示UI,只需在一个且唯一的UI线程中显示表单,并在非UI线程中执行非UI工作即可。@AwkwardCoder我从未使用或听说过“New Item”->“SplashScreen WPF”。这与制作新窗口有什么不同?Servy这是我在这一点上的最后手段,但我已经想到了这一点,你是对的,应该可以工作。这是启动屏幕的最简单的解决方案,所以为什么不使用它呢?你可以在UI线程上创建启动屏幕,并创建一个计时器,在你想要的延迟后触发。计时器的事件处理程序将在启动屏幕上调用Close方法。您是说这将消除访问错误?应该是这样的,您测试过了吗?错误:调用线程无法访问此对象,因为其他线程拥有它。表示需要调用。不幸的是,我没有使用WinForms。我正在使用WPF并在WinForms主机控件中托管OpenTK控件。
    private void splashControl_Paint(object sender, PaintEventArgs e)
    {
        // see the http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k%28SYSTEM.WINDOWS.FORMS.METHODINVOKER%29;k%28TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERSION%3dV4.0%22%29;k%28DevLang-CSHARP%29&rd=true
        if (!this.IsHandleCreated && !this.IsDisposed) return;

        if (this.InvokeRequired)
        {
            this.Invoke(new MethodInvoker(() => { splashControl_Paint(sender, e); }));
        }
        else
        {
            // place splashControl_Paint CODE HERE
        }
    }