在C#中启动一个STAThread

27
我是一名有用的助手,可以翻译文本。

我对C#和C#中的线程还不是很熟悉。

我正在尝试启动一个需要单线程公寓(STAThread)的函数。

但我无法编译以下代码:

该函数在名为MyClass的单独类中如下所示:

internal static string DoX(string n, string p)
        {
            // does some work here that requires STAThread
        }

我尝试在函数顶部使用属性 [STAThread],但这并没有起作用。

因此,我尝试创建一个新的线程,如下所示:

 Thread t = new Thread(new ThreadStart(MyClass.DoX));

但是这段代码无法编译(最佳重载方法具有无效参数错误)。然而在线示例非常相似 (此处为示例)。我做错了什么,如何简单地在新的STA线程中运行函数?
谢谢。

将此属性应用于入口点方法(C#和Visual Basic中的Main()方法)。它对其他方法没有影响。要设置您在代码中启动的线程的公寓状态,请在启动线程之前使用Thread.SetApartmentState方法。 - Blorgbeard
以前我是在我的主方法中进行这些操作,但现在我有一个服务,这些方法是运行契约,托管在终结点上,因此不再有主方法,因为我有一个WCF客户端从cmdlets调用。 - Saher Ahwal
如果我正在使用的命令行工具能够以STAThread模式调用函数启动,那就太好了。这种可能性存在吗? - Saher Ahwal
我不确定那是怎么工作的 - 我给你的问题打了WCF标签; 我认为你需要找一个比我更熟悉它的人 :) - Blorgbeard
好的,谢谢。我需要先创建线程,然后调用Thread.SetApartmentState方法。你知道如何创建一个线程吗?(这与WCF无关)我只是遇到了一个编译错误,我不明白为什么,因为我正在按照示例进行操作。 - Saher Ahwal
1个回答

54
Thread thread = new Thread(() => MyClass.DoX("abc", "def"));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
如果你需要这个值,你可以将其“捕获”到一个变量中,但是请注意,直到另一个线程结束后,该变量才会有值。
int retVal = 0;
Thread thread = new Thread(() => {
    retVal = MyClass.DoX("abc", "def");
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();

或许更简单的方式是:

Thread thread = new Thread(() => {
    int retVal = MyClass.DoX("abc", "def");
    // do something with retVal
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();

请问您能否更具体地说明一下SomethingToDo是什么?这是我无法构建/编译的部分。 - Saher Ahwal
@Saher 根据你的示例,我将其更改为 MyClass.DoX;关键点是:它必须是一个无返回值且无参数的方法,即 public void DoX() {...};如果 MyClass 是一个变量,那么 DoX 必须是一个实例方法;如果 MyClass 是一个类型,那么 DoX 必须是一个静态方法。 - Marc Gravell
@Saher 你在开玩笑吗?根据文档,我的类 MyClass.DOX (静态方法)是否具有适合 ThreadStart 的正确签名? - TomTom
2
@MarcGravell 在结尾处应该加上 thread.Join() 吧?否则没有返回值。 - Mr. Blond
3
在任何情况下,都不会返回价值,但问题是如何开始这样的线程。在末尾添加“Join”可能会让普通读者容易混淆,认为在很近的地方开始和加入一个线程是正常和预期的,但实际上这是非常罕见的(通常意味着您不应该首先使用线程,尽管STA可以说是这个规则的一个很好的例外)。 - Marc Gravell
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接