【发布时间】:2020-06-30 18:00:41
【问题描述】:
假设我的 Windows C# 应用中有一个 MyThread 类,如下所示:
public class MyThread
{
Thread TheThread;
public MyThread()
{
TheThread = new Thread(MyFunc);
}
public void StartIfNecessary()
{
if (!TheThread.IsAlive)
TheThread.Start();
}
private void MyFunc()
{
for (;;)
{
if (ThereIsStuffToDo)
DoSomeStuff();
}
}
}
效果很好。但是现在我意识到我可以通过使用 async/await 来提高我的线程效率:
public class MyThread
{
Thread TheThread;
public MyThread()
{
TheThread = new Thread(MyFunc);
}
public void StartIfNecessary()
{
if (!TheThread.IsAlive)
TheThread.Start();
}
private async void MyFunc()
{
for (;;)
{
DoSomeStuff();
await MoreStuffIsReady();
}
}
}
我现在看到的是,我第二次调用 StartIfNecessary() 时,TheThread.IsAlive 为假(顺便说一下,ThreadState 已停止)所以它调用 TheThread.Start(),然后抛出 ThreadStateException“线程正在运行或终止; 它无法重新启动”。但是我可以看到 DoMoreStuff() 仍在被调用,因此该函数实际上仍在执行。
我怀疑发生了什么,当我的线程遇到“等待”时,我创建的线程被停止,当 MoreStuffIsReady() 上的等待完成时,线程池中的一个线程被分配执行 DoSomeStuff() .因此,从技术上讲,我创建的线程已停止,但我创建的要处理的线程的函数仍在运行。
那么如何判断“MyFunc”是否仍处于活动状态?
我能想到 3 种方法来解决这个问题:
1) 添加一个“bool IsRunning”,在调用 TheThread.Start() 之前设置为 true,而 MyFunc() 在完成时设置为 false。这很简单,但需要我将所有内容都包装在 try/catch/finally 中,这并不可怕,但我希望有一种方法可以让操作系统或框架在这里帮助我,以防万一“MyFunc”在某些情况下死掉出乎我的意料。
2) 在 System.Threading 中的某处找到一些新函数,它将为我提供所需的信息。
3) 重新考虑整个事情——因为我的线程只停留了几毫秒,有没有办法在完全不创建线程的情况下完成同样的功能(在线程池之外)?以某种方式将“MyFunc”作为任务启动?
这种情况下的最佳做法?
【问题讨论】:
-
如果您能够重新开始,请发送Worker Service?
-
天哪。谷歌“async void被认为有害”以取得成功。
-
我可以通过使用 async/await 让我的线程更高效
-
MyFunc()方法在遇到await语句时立即返回。这就是那个线程的结尾。见标记重复。另请参阅 Stack Overflow 上数以千计的相关问题,在许多情况下实际上是相同的问题,这些问题有助于解释 async/await 的工作原理以及如何将这些技术应用到自己的代码中。
标签: c# asynchronous async-await task