您的位置:首页 > 移动开发 > Unity3D

WebClient 没有销毁 导致 Unity 卡死

2016-05-07 13:07 344 查看
最近在跟进游戏的资源更新功能,为了测试超时重试,我把访问对象设置为 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 。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: