最近在跟进游戏的资源更新功能,为了测试超时重试,我把访问对象设置为 google,众所周知google并不是不能访问,而是受到了长城dns污染,所以在浏览器中访问的时候,会过很久才会返回错误信息,这样的用来测试很方便。
在Unity 中使用 WebClient 对 Google 进行请求,大概要一分钟才会返回错误信息。
但是这时候发现了问题,如果在等待错误返回的中途,关闭游戏,然后再次点击 Play 按钮播放游戏的话,Unity就卡死了。
测试代码如下
using UnityEngine; using System.Collections; using System.Net; using System; public class NewBehaviourScript : MonoBehaviour { WebClient _webClient = null; Uri _uri = null; // Use this for initialization void Start() { StartCoroutine(Download()); } void OnGUI() { } IEnumerator Download() { _uri = new Uri("http://www.google.com"); Debug.Log("1"); _webClient = new WebClient(); _webClient.DownloadStringCompleted += DownLoadStringCompleted; _webClient.DownloadProgressChanged += DownLoadProgressChanged; _webClient.Disposed += Disposed; _webClient.DownloadStringAsync(_uri,"1"); yield break; } void DownLoadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { Debug.Log("DownLoadProgressChanged /" + e.UserState + " /" + e.ProgressPercentage + " / " + e.BytesReceived + " /" + e.TotalBytesToReceive); } void DownLoadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { Debug.Log("DownLoadStringCompleted /"+e.UserState+" /" + e.Cancelled + " / " + e.Error+" /"+e.Result); } void Disposed(object sender, EventArgs e) { Debug.Log("Disposed " + e.ToString()); } }
在公司一直没有发现,昨天晚上在家里测试的时候……
发现关闭游戏,过一段时间后,居然在Cosoler 里面打印出了 访问错误的信息。
这时候才想起来,WebClient 是多线程的,如果我没有销毁它,它就在后台一直执行着。
于是猜测第二次Play 的时候,是不是被 WebClient 卡住了?
于是我一直等待……
果然等了差不多半分钟,游戏启动了……
而且,如果等错误信息在控制台打印出来之后,再去Play 游戏,是马上可以 Play 游戏的。
所以,这次Unity 卡住的问题就是因为 WebClient 没有被销毁 引起的。
解决方法就是添加销毁 WebClient 的代码:
void OnDestroy() { _webClient.CancelAsync(); _webClient.Dispose(); _webClient = null; }
随后发现了其它问题。
当销毁WebClient 之后,再第二次 new WebClient,即使第二个WebClient 销毁了,Unity 仍然会卡死!
测试代码如下‘’
using UnityEngine; using System.Collections; using System.Net; using System; public class NewBehaviourScript : MonoBehaviour { WebClient _webClient = null; Uri _uri = null; // Use this for initialization void Start() { } void OnGUI() { if (GUILayout.Button("Start")) { StartCoroutine(Download()); } if (GUILayout.Button("Stop")) { StartCoroutine(Stop()); } } IEnumerator Download() { _uri = new Uri("http://www.google.com"); Debug.Log("1"); _webClient = new WebClient(); _webClient.DownloadStringCompleted += DownLoadStringCompleted; _webClient.DownloadProgressChanged += DownLoadProgressChanged; _webClient.Disposed += Disposed; _webClient.DownloadStringAsync(_uri, "1"); yield return new WaitForSeconds(1.0f); _webClient.CancelAsync(); yield return new WaitForSeconds(1.0f); _webClient.Dispose(); yield return new WaitForSeconds(1.0f); _webClient = null; yield return new WaitForSeconds(1.0f); Debug.Log("2"); _webClient = new WebClient(); _webClient.DownloadStringCompleted += DownLoadStringCompleted; _webClient.DownloadProgressChanged += DownLoadProgressChanged; _webClient.Disposed += Disposed; _webClient.DownloadStringAsync(_uri, "2"); yield break; } IEnumerator Stop() { yield return new WaitForSeconds(1.0f); _webClient.CancelAsync(); yield return new WaitForSeconds(1.0f); _webClient.Dispose(); yield return new WaitForSeconds(1.0f); _webClient = null; } void DownLoadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { Debug.Log("DownLoadProgressChanged /" + e.UserState + " /" + e.ProgressPercentage + " / " + e.BytesReceived + " /" + e.TotalBytesToReceive); } void DownLoadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { Debug.Log("DownLoadStringCompleted /" + e.UserState + " /" + e.Cancelled + " / " + e.Error + " /" + e.Result); } void Disposed(object sender, EventArgs e) { Debug.Log("Disposed " + e.ToString()); } }
目前只好保持一个 WebClient 。。。