C# 在Mono.Net线程中,线程是否会粘住,或者?
这是Unity/Mono,但任何.Net 想象一下这样的代码C# 在Mono.Net线程中,线程是否会粘住,或者?,c#,c,.net,multithreading,unity3d,C#,C,.net,Multithreading,Unity3d,这是Unity/Mono,但任何.Net 想象一下这样的代码 using System.Threading; using System.Runtime.InteropServices; public class Example: MonoBehaviour { [DllImport("__Internal")] private static extern void long_function(); [DllImport("__Internal")] private stati
using System.Threading;
using System.Runtime.InteropServices;
public class Example: MonoBehaviour {
[DllImport("__Internal")] private static extern void long_function();
[DllImport("__Internal")] private static extern void short_function();
public Thread happyThread;
public void Test() {
happyThread = new Thread(LongTest);
happyThread.Start();
}
private void LongTest() { long_function(); }
private void ShortTest() { short_function(); }
}
我们运行Test
,从而启动了C库中的long_函数。它是在另一个线程上启动的。(“快乐阅读”)
假设运行需要60秒
在这段时间结束时,happyThread
是否不再存在?或者它仍然存在于示例范围中?或者你能保留它还是什么
假设我们知道long\u函数已完成。然后我想调用ShortTest
,从而调用short\u函数
。你能这样做吗
早些时候我们这样做了
happyThread = new Thread(LongTest);
我们现在可以将线程的“内容”更改为
happyThread.newStuff( ShortTest());
happyThread.StartAgain();
happyThread.newStuff( ShortTest());
happyThread.StartAgain();
或者这是愚蠢和毫无意义的
我会仅仅在另一个新线程上再次开始短测试吗
假设库有一个简单的全局变量intk
因此TBC,构建到静态库中的C文件在顶部如下所示:
//文件happyLibrary.c Fattie(TM)2019
#包括
#包括
int k=7;//(注意,在真正的应用程序中,您几乎肯定希望使用volatile)
空长函数
{
...
…哪个long\u函数
设置为42。事实上,short\u函数
以后也可以访问该值吗?或者?仅当我使用相同的线程或其他东西时?同样,k
是全局函数
如果你不得不启动无数的小任务,如果重复使用happyThread可能有性能优势,如果你可以重用它们
(我完全理解,简单地说,long_函数将继续存在,并使用short_函数概念提供对主线程的回调;但是,呃,我想知道我上面问的是什么。你能“重复使用”线程吗?你能“再次使用”它吗?)
在那个时候结束时,happyThread是否不再存在?或者它仍然存在于示例范围内?或者你能保留它或其他东西吗
当线程上调用的函数(在本例中为LongTest
)完成时,线程的生命周期将结束。只要您在happyThread
(您可以自己查看!happyThread.ManagedThreadId
即使完成后仍将返回线程的ID),但无法重新启动。您可以通过调用happyThread.ThreadState
(此时将返回stopped
)来检查线程的状态
我们现在可以将线程的“内容”更改为
happyThread.newStuff( ShortTest());
happyThread.StartAgain();
happyThread.newStuff( ShortTest());
happyThread.StartAgain();
不可以。不能将新函数绑定到已终止的线程,如果再次尝试调用happyThread.Start()
,它将抛出一个已启动的线程。
我会仅仅在另一个新线程上再次开始短测试吗
是的。您必须在新线程(ShortTest)
上启动ShortTest
(或者您可以将它添加到LongTest()
方法的末尾。在线程上启动的任何新方法都将在该线程上运行)。但是,您可以在旧的happyThread
上调用新线程。因此happyThread=新线程(ShortTest())
将很高兴再次启动!在第一个线程用完之前,您甚至可以在happyThread
上启动一个新线程。因此
Thread happyThread = new Thread(LongTest());//say this runs for 1 minute
happyThread.Start();
happyThread = new Thread(ShortTest());//this will start without a problem
happyThread.Start();
也会很高兴地开始。但是请注意,这实际上不应该这样做。它会使您丢失对运行最长时间的线程的引用。(尽管先调用LongTest
,ShortTest
,但如果该线程恰好首先触发,那么实际上可能会首先开始运行……这确实远不理想,但只是想表明这是可能的。)
short_功能是否也会在以后访问该值
是的,我们假设int k
是公共的和全局的,并且只在主线程上运行。您可以将其值从long\u function
设置为42,然后如果需要,可以在不同的线程上从short\u function
读取int k
的值。现在请注意,在设置/获取多个变量时必须小心我用线来防止它
但是,如果在单独线程上运行的方法中定义int k
,则当线程终止时,它将超出范围,就像函数终止时在函数内部初始化的任何变量一样
您可以使用volatile
关键字指示变量可能被多个线程修改
如果你不得不启动无数的小任务
如果要启动/关闭大量线程,您可能需要使用
你能“重复使用”一个线程吗?你能再次“进入”它吗
所以这一切都归结为否。一旦一个线程死亡,它就无法再次启动,请参阅该特定主题
但是,作为替代方法,您可以在应用程序期间保持线程的活动状态,前提是您知道您将多次甚至连续地调用线程(例如,我使用此方法在后台保持TCP连接,该连接需要始终可访问)。可以这样做:
Void Start()
{
Thread happyThread = new thread(() => KeepAlivethread(1000));//short, easy way to create a delegate so you can pass parameters to your thread aswell!
happyThread.Start();
}
volatile bool keepThreadAlive = true;//volatile because it may be accessed from another thread
private void KeepAliveThread(int timeout)
{
Debug.Log("Thread started with id: " + Thread.CurrentThread.ManagedThreadId);
while (keepThreadAlive)
{
//do something, maybe have an event that calls to ShortTest.
Thread.Sleep(timeout);
}
Debug.Log("Thread terminating with id: " + Thread.CurrentThread.ManagedThreadId);
}
现在,此线程将在后台继续运行,直到您设置keepThreadAlive=false
,然后它将优雅地终止。(这样做,您就不必thread.Abort()
,这是不好的!(更多信息请参见前面链接的so帖子的答案)ThreadPool?…这很奇怪,出于某种原因,答案发布了两次……但第二次只是部分发布……有时发生在糟糕的互联网连接上;)保持住!@remy_rm让我们转到它说的地方:“当线程死了,可怜的k也死了。”k是一个全局的(注意,我编辑了这个问题,并显示了k在C源代码中声明的位置)..这肯定是不对的,k仍然存在,当线程正确死亡时设置为42??(是的,我