c# - 在计时器中使用QueueUserWorkItem时发生ThreadStateException

标签 c# winforms multithreading clipboard

我的WinForms应用程序中有一个ThreadStateException。

复制步骤:

  • 创建简单的winforms应用程序
  • 添加一个计时器
  • 在click事件中,请执行以下操作:
    timer1.Interval = 1000;
    timer1.Tick += timer1_Tick;
    timer1.Start();
    


    void timer1_Tick(object sender, EventArgs e)
    {
        ThreadPool.QueueUserWorkItem(delegate
        {
            StringCollection paths =
                new StringCollection { @"c:\my.txt", @"c:\my.png" };
            Clipboard.SetFileDropList(paths);
        });
    }
    

  • 异常告诉我:

    Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it.



    但是主体已经具有[STAThread]属性。

    怎么解决呢?

    最佳答案

    Thread.SetApartmentState()方法在这里很重要。剪贴板是一个COM对象,它不是线程安全的。有许多Windows功能具有这种行为,Drag + Drop和Shell对话框(如OpenFileDialog)是其他示例。

    您不能设置线程池线程的单元状态,它始终是MTA(多线程单元)。您可以在常规线程上使用,但附加的STA要求是您还应泵送消息循环(Application.Run)。这又给您带来了完全相同的问题:您不能阻塞或花费很长时间执行代码。

    简单的解决方案是执行在线程上执行需要很长时间的任何事情。并从UI线程进行Clipboard调用。使用Control.BeginInvoke()或更好的BackgroundWorker.RunWorkerCompleted。

    关于c# - 在计时器中使用QueueUserWorkItem时发生ThreadStateException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2990273/

    相关文章:

    c++ - Thread Building Blocks 流程图 — 类似 limiter_node 的东西,不会丢弃消息

    c - 父子进程打印

    c# - 为什么无限在Windows 10控制台中打印为 "8"?

    c# - iPhone v 卡中的变音符号

    c++ - 如何使用按钮在表单之间导航?

    c# - 带有 CheckBox 单元格问题的 DataGridView

    winforms - VS2010 Winforms Usercontrol 更改未显示在父窗体中

    java - 使用 final 字段的成本

    c# - 数据绑定(bind)误解

    c# - TFS 构建中的 ClickOnce list 应用程序