Unity---关于线程和携程的中断的一个测试(暂时是这个名字)
很纠结,其实这些我感觉不需要在开一个,但是上篇确实有点长了 = =
Unity----事件类型----1 -> https://blog.****.net/MikuLingSSS/article/details/82357104
================================================================================================
首先,做一个小的实验,代码如下
2018-10-30:我犯了一个致命的错误,我原先以为 yield return 0.1f; 是等待0.1s之后执行,后来测试发现 waitForSource 才是等待一定时间之后再次执行,下面的代码就不修改了,
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
using System;
public class TimeRunningMethod: MonoBehaviour
{
Thread testThread;
void Start()
{
testThread = new Thread(() =>
{
try
{
Debug.Log("System.Threading->Start");
while (true)
{
Debug.Log("System.Threaing->Running!!!!!!!!!!");
Thread.Sleep(100);
}
}
catch (Exception ex)
{
Debug.LogError("Thread Error Logs->" + ex.Message);
}
});
testThread.Start();
StartCoroutine(test());
IsInvokeStart = true;
InvokeRepeating("printf", 0, 0.1f); // 这个方法,应该是类似于Timer.Interval
}
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
StopCoroutine(test());
Debug.LogWarning("Ienumerator->Stop");
}
if (Input.GetKeyDown(KeyCode.S))
{
CancelInvoke("printf");
Debug.LogWarning("InvokeRepeating->Stop");
}
if (Input.GetKeyDown(KeyCode.D))
{
testThread.Abort();
testThread = null;
Debug.LogWarning("System.Threading->Stop");
Debug.Log(testThread == null ? "11" : "00"); // 输出11
}
}
private bool IsInvokeStart;
void printf()
{
if (IsInvokeStart)
{
IsInvokeStart = false;
Debug.LogWarning("InvokeRepeating->Start");
}
Debug.Log("InvokeRepeating->hello world!!!!!!!!!!");
}
IEnumerator test()
{
Debug.LogWarning("Ienumerator->Start");
while (true)
{
Debug.Log("Ienumerator->hello world!!!!!!!!!!");
yield return 0.1f;
}
}
private void OnDestroy()
{
//if (testThread != null)
//{
//testThread.Abort();
//}
}
}
直接退出:
可以看到,如果不是正常退出的话,由Unity主线程创建的子线程是不会随着main线程退出而退出的,这时候就需要我们自己手动去释放线程资源,解决方案,吧OnDestroy里面的代码块取消注释,这也是我前两篇Socket里面最后在OnDestroy里面写销毁代码的原因,
注意,如果你使用了多线程,那么最好写一个特殊的单例来存储所有的关于线程的创建和释放的方法,原因大家应该都清楚,就是场景切换之后的脚本问题。。。
====================================使用Update里面的按键结束=======================================
注意:线程的Abort,如我上一篇中所说,其实是让线程抛出一个异常,所以catch里面的代码块会一并执行
可以看到,协程的Stop并没有起到我们想要的效果,说一下我的想法,当我们执行Stop的时候,他其实就应该Return掉,但是他内部的条件一直为true,所以造成了一种无限goto的现象,所以根本走不到Return这个条件,而这种情况,我们可以使用特殊的变量来结束
修改一下代码,新加一个Manager的类
class Manager
{
public static bool IsStopIenumerator = false;
}
//////////////////////TimeRunningMethod修改这些
void Update()
{
try // 关于协程的退出改成这样
{
if (Input.GetKeyDown(KeyCode.A))
{
StopCoroutine(test());
Debug.LogWarning("Ienumerator->Stop");
Manager.IsStopIenumerator = true;
}
}
catch (Exception ex)
{
Debug.LogError("Stop Ienumerator->" + ex.Message);
}
// ....... 下面的代码都没变
}
IEnumerator test() // 协程
{
Debug.LogWarning("Ienumerator->Start");
while (true)
{
if (Manager.IsStopIenumerator)
throw new Exception("Ienumerator Stop");
Debug.Log("Ienumerator->hello world!!!!!!!!!!");
yield return 0.1f;
}
}
运行结果:
不过,详细看代码和输出会发现,协程明显比其他两个函数执行的次数要多,大概是因为帧数吧,其他两个方法的0.1s比较接近