C# 中是否可以等待线程?

问题描述 投票:0回答:2

我面临的情况是,我必须手动生成一个新线程,这样我才能调用

.SetApartmentState(ApartmentState.STA)
。这意味着(据我所知)我无法使用
Task
。但我想知道线程何时完成运行,例如与
await
一起使用的
async
。然而,我能想到的最好的办法是一个循环,不断检查
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 线程,因此任何小的性能影响都可以(例如几百毫秒)。

c# multithreading sta
2个回答
0
投票

这是一个扩展方法,您可以使用它来启用线程等待(受本文启发:await everything)。

public static TaskAwaiter GetAwaiter(this Thread thread)
{
    ArgumentNullException.ThrowIfNull(thread);
    return Task.Run(async () =>
    {
        using PeriodicTimer timer = new(TimeSpan.FromMilliseconds(100));
        while (thread.IsAlive) await timer.WaitForNextTickAsync();
        thread.Join(); // Let's be extra sure that the thread has finished
    }).GetAwaiter();
}

此实现使用

IsAlive
(.NET 6) 每 100 毫秒池化线程的
PeriodicTimer
属性。这意味着等待并不是完全被动的(存在一些开销),并且等待的完成不是瞬时的。线程终止和等待完成之间的间隔通常会低于 100 毫秒,但如果
ThreadPool
饱和,间隔可能会变大(
PeriodicTimer
依赖于
ThreadPool
来标记其事件) .

使用示例:

Thread thread = new(() =>
{ 
    Thread.Sleep(1000); // Simulate some background work
});
thread.IsBackground = true;
thread.Start();
await thread; // Wait asynchronously until the thread is completed

对于不依赖于

GetAwaiter
类的
PeriodicTimer
版本,因此它可以与早于 .NET 6 的 .NET 版本一起使用,请参阅此答案的 第 3 次修订版


-1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.