【问题标题】:C# Thread - STAThreadAttribute exceptionC# 线程 - STAThreadAttribute 异常
【发布时间】:2016-05-13 16:17:39
【问题描述】:

我会尽力解释。 基本上我在无形系统托盘应用程序中使用全局热键。 为此,我正在使用此热键管理器:Global hotkey in console application 调用热键时,我开始收到此异常:

当前线程必须设置为单线程单元 (STA) 模式 在可以进行 OLE 调用之前。确保您的 Main 函数具有 STAThreadAttribute 标记就可以了。

我“修复”异常的方式是:https://stackoverflow.com/a/6373700/6329242 我的全局热键开始工作,除了一个,我得到了同样的例外。实在找不到解决办法。

我是这样称呼他们的:

      static void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
    {
        switch (e.Key)
        {
            case Keys.D1:
                CaptureAreaOfScreenForm caos2 = new CaptureAreaOfScreenForm();
                var thread1 = new Thread(new ParameterizedThreadStart(param => { caos2.Show(); }));
                thread1.SetApartmentState(ApartmentState.STA);
                thread1.Start();
                break;
            case Keys.D2:
                CaptureWorkingArea cwa2 = new CaptureWorkingArea();
                var thread2 = new Thread(new ParameterizedThreadStart(param => { cwa2.CaptureTheWorkingArea(); }));
                thread2.SetApartmentState(ApartmentState.STA);
                thread2.Start();
                break;
            case Keys.D3:
                CaptureFullScreen cfs2 = new CaptureFullScreen();
                var thread3 = new Thread(new ParameterizedThreadStart(param => { cfs2.CaptureDesktop(); }));
                thread3.SetApartmentState(ApartmentState.STA);
                thread3.Start();
                break;
            case Keys.D4:
                CaptureAllScreens cas2 = new CaptureAllScreens();
                var thread4 = new Thread(new ParameterizedThreadStart(param => { cas2.CaptureScreens(); }));
                thread4.SetApartmentState(ApartmentState.STA);
                thread4.Start();
                break;
            case Keys.D5:
                UploadFromFile uff2 = new UploadFromFile();
                var thread5 = new Thread(new ParameterizedThreadStart(param => { uff2.UploadFile(); }));
                thread5.SetApartmentState(ApartmentState.STA);
                thread5.Start();
                break;
        }
        //collect the garbage
        GC.Collect();
    }

(问题是 Keys.D1)。有问题的和其他的区别是我调用了一个表单类。 (其他人工作正常)

附:如果我可以添加一些有助于解决它的东西或者更多的东西告诉我这样做,我就是编程新手。谢谢。

【问题讨论】:

  • 您是否尝试过调用 ShowDialog 而不是 Show?顺便说一句,您真的应该在问题正文中包含代码,而不是作为附件。
  • 是的,我尝试了 ShowDialog - 它给了我同样的异常,而且我不能真正使用它,因为我正在使用表单来绘制一个矩形,然后关闭它(使用 ShowDialog 它会粘在屏幕上)。

标签: c#


【解决方案1】:

注意。这是相当狡猾的——Windows 窗体旨在通过单个线程运行所有窗体和控件,但这并不意味着你不会让它工作。您确实需要确保在它们运行的​​同一线程中创建事物,因此请尝试更改它以便您也在线程内创建表单...

  static void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
    {
        switch (e.Key)
        {
            case Keys.D1:

                var thread1 = new Thread(new ParameterizedThreadStart(param => { CaptureAreaOfScreenForm caos2 = new CaptureAreaOfScreenForm();caos2.Show(); }));
                thread1.SetApartmentState(ApartmentState.STA);
                thread1.Start();
                break;
            case Keys.D2:
                CaptureWorkingArea cwa2 = new CaptureWorkingArea();
                var thread2 = new Thread(new ParameterizedThreadStart(param => { cwa2.CaptureTheWorkingArea(); }));
                thread2.SetApartmentState(ApartmentState.STA);
                thread2.Start();
                break;
            case Keys.D3:
                CaptureFullScreen cfs2 = new CaptureFullScreen();
                var thread3 = new Thread(new ParameterizedThreadStart(param => { cfs2.CaptureDesktop(); }));
                thread3.SetApartmentState(ApartmentState.STA);
                thread3.Start();
                break;
            case Keys.D4:
                CaptureAllScreens cas2 = new CaptureAllScreens();
                var thread4 = new Thread(new ParameterizedThreadStart(param => { cas2.CaptureScreens(); }));
                thread4.SetApartmentState(ApartmentState.STA);
                thread4.Start();
                break;
            case Keys.D5:
                UploadFromFile uff2 = new UploadFromFile();
                var thread5 = new Thread(new ParameterizedThreadStart(param => { uff2.UploadFile(); }));
                thread5.SetApartmentState(ApartmentState.STA);
                thread5.Start();
                break;
        }
        //collect the garbage
        GC.Collect();
    }

【讨论】:

  • 基本 Windows 线程 101:STA 和 UI 中的所有对象必须在 te UI 线程上创建。
  • @TomTom 我没有使用过 WPF,但我的印象只适用于 Windows 窗体?
  • 我不得不将其更改为 ShowDialog,否则我的表单在内部创建时只是闪烁,但它成功了 wooooooooo!非常感谢你让我开心!得做一些改变它会是一个繁荣!泰泰。
  • 不,它是一切的基础。首先,它使编程控件变得更容易......其次它是 WINDOWS 的基础......整个 UI 核心都遵循这种范式。
  • @wizzardmr42 这是一个非常有用的方法。每个进程可以有多个消息循环(每个都在自己的线程中),但这很棘手。多线程非常困难,多线程 UI 也不例外。您真的只想在必要时使用多线程,并且确保 UI 从任何线程正常工作是很多工作,只需确保仅从 UI 线程访问 UI 就可以完全避免这些工作。这对于 Winforms 和 WPF 或 HTML/JS 是一样的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-10
  • 2011-05-27
  • 2014-09-10
  • 2013-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多