在C#中,是否可能等待Thread?

4

我目前需要手动创建一个新线程,以便能够调用 .SetApartmentState(ApartmentState.STA)。这意味着(据我所知)我不能使用 Task。但是我想知道线程何时完成运行,就像可以与async一起使用的await一样。然而,我能想到的最好方法只是循环不断检查Thread.IsAlive,如下所示:

var thread = new Thread(() =>
{ 
    // my code here 
});

thread.SetApartmentState(ApartmentState.STA);
thread.Start();

while(thread.IsAlive)
{
    // Wait 100 ms
    Thread.Sleep(100);
}

只要线程不陷入停顿,这段代码应该是有效的,但它看起来有些笨拙。有没有更聪明的方法来检查线程何时完成(或死亡)?

这只是为了避免阻塞GUI线程,所以任何小的性能损失都可以接受(比如几百毫秒)。


3
你似乎在寻找一个非常奇怪的解决方案,相反,请解释一下你想要解决的问题是什么。 - aybe
4
Thread.Join()是一个方法,它可以暂停当前线程的执行,直到调用这个方法的线程完成执行为止。 - Ian Mercer
1
我想做的基本上是 await Task.Run()。但由于STA约束,我无法这样做。我可以使用Thread.Join(),但这是否会同时阻塞UI线程呢? - Jakob Busk Sørensen
2
这个问题能解决你的实际问题吗?https://dev59.com/rGQn5IYBdhLWcg3wmH8s - yaakov
如果Thread是UI线程,那么Thread.Join()会阻塞UI。 - Soleil
显示剩余3条评论
2个回答

1

这里是一个扩展方法,您可以使用它来启用线程等待(灵感来自于这篇文章:等待任何东西)。

public static TaskAwaiter GetAwaiter(this Thread thread)
{
    return Task.Run(async () =>
    {
        while (thread.IsAlive)
        {
            await Task.Delay(100).ConfigureAwait(false);
        }
    }).GetAwaiter();
}

使用示例:

var thread = new Thread(() =>
{ 
    Thread.Sleep(1000); // Simulate some background work
});
thread.IsBackground = true;
thread.Start();
await thread; // Wait asynchronously until the thread is completed
thread.Join(); // If you want to be extra sure that the thread has finished

真是个好主意。您觉得能否以某种方式将thread.SetApartmentState(ApartmentState.STA)thread.Start()包含进去?这样它就可以像传统的异步方法一样运行了... - Jakob Busk Sørensen
GetAwaiter 方法只是为线程启用 await 运算符。线程的创建及其所需属性可以像往常一样完成。我在答案中更新了一个完整的示例。 - Theodor Zoulias

-1
你可以使用BackgroundWorker类吗?它有一个事件可以报告它何时完成。

我尝试过了。似乎 BackgroundWorker 类在 MTA 中运行,无法更改。 - Jakob Busk Sørensen

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