这是在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 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_function
。它在另一个线程上启动。 (“ happyThread”)
说运行需要60秒。
在那之后,happyThread
不再存在了吗?还是在示例范围内?还是可以保留它或其他东西?
比方说,我们知道long_function
完成了。然后,我要呼叫ShortTest
,因此要呼叫short_function
。你能做这样的事吗?。
我们之前做过
happyThread = new Thread(LongTest);
我们现在可以将线程的“内容”“更改”为
happyThread.newStuff( ShortTest());
happyThread.StartAgain();
还是那个愚蠢而毫无意义的东西?
仅在另一个新线程上再次启动ShortTest吗?
说该库具有一个简单的 global 变量int k
...
因此,TBC,内置于静态库的C文件在顶部看起来像这样:
// file happyLibrary.c Fattie(TM) 2019
#include <stdio.h>
#include <CoreFoundation/CoreFoundation.h>
int k = 7; // (NB you almost certainly want volatile here in real apps)
void long_function
{
...
...,其中long_function
设置为42。实际上.... short_function
以后也可以访问该值?要么?仅当我使用相同的线程或其他东西时?同样,k
是一个全局全局变量。
如果您必须启动成千上万的小任务,如果重新使用happyThread可能会带来性能优势,并且可以重用'em ??
(我完全赞赏,long_function会一直保留在那里,并使用short_function概念提供对主线程的回调;但是,我想知道我在上面提出的问题。 -使用“线程?您可以再次进入它吗?”
答案 0 :(得分:3)
- 在那段时间的尽头,happyThread不再存在了吗?还是在示例范围内?还是可以保留它或其他东西?
在线程上调用的函数(在这种情况下为LongTest
)完成后,线程的生命周期将结束。只要您在happyThread
中有对该线程的引用,该线程仍然存在(您可以自己查看!happyThread.ManagedThreadId
仍会返回该线程的ID,即使已完成该线程也是如此),但是它不能重新启动。您可以通过调用happyThread.ThreadState
(此时将返回stopped
)来检查线程的状态。
我们现在可以将线程的“内容”“更改”为
happyThread.newStuff( ShortTest()); happyThread.StartAgain();
不,您不能。您无法将新函数绑定到已终止的线程,并且如果尝试再次在其上调用happyThread.Start()
,它将抛出ThreadStateException Thread has already been started.
。
我会只是在另一个新线程上再次启动ShortTest吗?
是的。您将必须在ShortTest
上启动new Thread(ShortTest)
(或者您可以将其添加到LongTest()
方法的末尾。在线程上启动的任何新方法都将在该线程上运行)。但是,您可以在旧的happyThread
上调用新线程。因此happyThread = new Thread(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
的线程的引用。 (尽管首先调用了LongTest
,但如果该线程恰好触发了ShortTest
,实际上它可能会首先开始运行...这确实很不理想,但只是想展示它 is < / em>。)
short_function还会在以后访问该值吗?
是的,我们假设int k
是公共的和全局的,并且仅在主线程上运行。您可以将其值从long_function
设置为42,然后根据需要在不同的 线程上从int k
读取short_function
的值。现在请注意,您必须谨慎设置/获取多个线程中的变量,以防止出现race conditions。
但是,如果您在运行在单独线程上的方法中定义int k
,则当线程死亡时,它将超出范围,就像在函数用完时在函数内部初始化的任何变量一样。 / p>
您可以使用volatile
关键字来指示一个变量可能被多个线程修改。 Msdn docs
如果您必须启动不计其数的小任务...
如果您要启动/关闭许多线程,则可能要使用ThreadPools
您可以“重用”线程吗?您可以再次“加入”吗?
所以一切都归结为否。线程死亡后,将无法再次启动,有关该特定主题的信息,也请参见this SO post。
但是,作为替代方案,您可以在应用程序运行期间保持线程处于活动状态,如果您知道要多次甚至连续调用它(例如,我使用它在后台保持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帖子的答案)