您的位置:首页 > 其它

silverlight游戏设计(二)资源管理篇(上)--实现一个多任务资源下载器

2010-12-21 22:32 543 查看
我在silverlight游戏设计(一)主程序加载器这篇文章中写的那个加载器中其实已经包含了一个下载器。不过本篇需要的是一个在游戏运行时动态执行的下载器,这两者有什么区别呢?一方面在于前篇的那个下载器是串行下载所有文件,而对于一个正在运行的网游,因为我们对大部分资源(比如图片、脚本等)采取动态加载的策略,所以它随时都有可能去请求下载,也就是需要同时进行更多的下载任务;二是我们这个下载器与接下来资源管理服务时紧密相关,所以需要重新设计新的接口。

设计要点

DownloadDelegaternamespace Sopaco.Silverlight.Insfrastructure.Net.DownloadActivator
{
public class DownloadDelegater : IDisposable
{
class InnerBuffData
{
public Uri Uri
{
get;
set;
}
public DownloadResultEventHandler Handler
{
get;
set;
}
}

#region Constaints
private readonly static int DEFAULT_CONNECTION_IN_POOL = 5;
#endregion
#region Fields
/// <summary>
/// 池化WebClient
/// </summary>
private IGenericPool<WebClient> _webClients = new GenericPool<WebClient>();
/// <summary>
/// 缓冲,当WebClient数量达到限制时将需要等待的资源Uri放到这里。
/// </summary>
private Queue<InnerBuffData> _buffTargets = new Queue<InnerBuffData>();
/// <summary>
/// 最大启用的WebClient数量
/// </summary>
private int _maxConnectionInPool = DEFAULT_CONNECTION_IN_POOL;
/// <summary>
/// 当前进行中的WebClient数量
/// </summary>
private int _currentWorkersNum = 0;
#endregion

#region lockers
private object _lock_CurrentWorkersNum = new object();
private object _lock_BuffTargets = new object();
#endregion

#region ctors
public DownloadDelegater()
{

}
#endregion
#region Properties
public int MaxConnectionInPool
{
get
{
return _maxConnectionInPool;
}
set
{
_maxConnectionInPool = value;
}
}
#endregion
public void Download(Uri uri, DownloadResultEventHandler callback)
{
if(_currentWorkersNum + 1 > _maxConnectionInPool)
{
enqueue(new InnerBuffData() { Uri = uri, Handler = callback });
return;
}
var client = _webClients.Detach();
client.OpenReadCompleted += onDownloadResultArrive;
client.OpenReadAsync(uri, callback);
increaseRefCounter();
}

#region IDisposable Members

public void Dispose()
{
disposeWebclientPool();
_webClients.Dispose();
}

#endregion
#region Private Helper Methods
private void disposeWebclientPool()
{
_webClients.Compact(0);
}
private void onDownloadResultArrive(object sender, OpenReadCompletedEventArgs args)
{
var callback = args.UserState as DownloadResultEventHandler;
var client = sender as WebClient;
if(args.Result != null && args.Error == null && !args.Cancelled)
{
var memStream = new MemoryStream();
args.Result.CopyTo(memStream);
memStream.ResetPosition();
callback(memStream, DownloadStatus.Completed);
}
else
{
if(args.Cancelled)
{
callback(null, DownloadStatus.Canceled);
}
else
{
callback(null, DownloadStatus.Error);
}
}
lock (_lock_BuffTargets)
{
if (_buffTargets.Count != 0)
{
var targetInfo = dequeue();
client.OpenReadAsync(targetInfo.Uri, targetInfo.Handler);
}
else
{
client.OpenReadCompleted -= onDownloadResultArrive;
decreaseRefCounter();
_webClients.Attach(client);
return;
}
}
}
private void increaseRefCounter()
{
lock (_lock_CurrentWorkersNum)
{
_currentWorkersNum++;
}
}
private void decreaseRefCounter()
{
lock (_lock_CurrentWorkersNum)
{
_currentWorkersNum--;
}
}
private void enqueue(InnerBuffData data)
{
lock(_lock_BuffTargets)
{
_buffTargets.Enqueue(data);
}
}
private InnerBuffData dequeue()
{
lock(_lock_BuffTargets)
{
return _buffTargets.Dequeue();
}
}
#endregion
}
}完整源码下载


[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐