UnityWebRequest的异步写法
using System;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
public class Example : MonoBehaviour
{
/// <summary>
/// 任务取消源
/// </summary>
CancellationTokenSource ts = new CancellationTokenSource();
void Start()
{
SynchronizationContext.SetSynchronizationContext(SynchronizationContext.Current);
Test();
}
private void OnDestroy()
{
// 取消访问
ts.Cancel();
}
async void Test()
{
string url = "http://www.baidu.com";
try
{
// 更新进度
var progress = new Progress<float>(v =>
{
Debug.Log(v);
});
// ts.Token 创建取消通知
// 访问链接
var www = await RequestHelper.GetAsync(url, null, progress, ts.Token, 5000);
// 假如取消了访问,因为异步内部抛出了AggregateException异常,下面语句不再执行
Debug.Log(www.downloadHandler.text.Length);
}
catch(Exception ex)
{
Debug.LogError(ex);
}
}
}
public class RequestHelper
{
public static async Task<UnityWebRequest> GetAsync(string url, int timeout = 10000)
{
var request = UnityGetRequest.Create(url, null, timeout);
while (!request.isDone)
{
await Task.Delay(16);
}
return request.unityWebRequest;
}
public static async Task<UnityWebRequest> GetAsync(string url, IProgress<float> progress, int timeout = 10000)
{
var request = UnityGetRequest.Create(url, null, timeout);
while (!request.isDone)
{
progress.Report(request.Progress);
await Task.Delay(16);
}
return request.unityWebRequest;
}
public static async Task<UnityWebRequest> GetAsync(string url, IProgress<float> progress, CancellationToken token, int timeout = 10000)
{
var request = UnityGetRequest.Create(url, null, timeout);
while (!request.isDone)
{
if (token.IsCancellationRequested)
{
token.ThrowIfCancellationRequested();
}
progress.Report(request.Progress);
await Task.Delay(16);
}
return request.unityWebRequest;
}
public static async Task<UnityWebRequest> GetAsync(string url, WWWForm formData, IProgress<float> progress, CancellationToken token, int timeout=10000)
{
var request = UnityGetRequest.Create(url, formData, timeout);
while (!request.isDone)
{
if (token.IsCancellationRequested)
{
token.ThrowIfCancellationRequested();
}
progress.Report(request.Progress);
await Task.Delay(16);
}
return request.unityWebRequest;
}
public static async Task<UnityWebRequest> PostAsync(string url, WWWForm formData, IProgress<float> progress, CancellationToken token, int timeout = 10000)
{
var request = UnityPostRequest.Create(url, formData, timeout);
while (!request.isDone)
{
if (token.IsCancellationRequested)
{
token.ThrowIfCancellationRequested();
}
progress.Report(request.Progress);
await Task.Delay(16);
}
return request.unityWebRequest;
}
interface IUnityWebRequest
{
bool isDone { get; }
float Progress { get; }
UnityWebRequest unityWebRequest { get; }
}
class UnityGetRequest : IUnityWebRequest
{
UnityWebRequest request;
bool IUnityWebRequest.isDone => request.isDone;
float IUnityWebRequest.Progress => request.downloadProgress;
UnityWebRequest IUnityWebRequest.unityWebRequest => request;
public static IUnityWebRequest Create(string url, WWWForm formData, int timeout)
{
UnityGetRequest unityGetRequest = new UnityGetRequest();
unityGetRequest.request = UnityWebRequest.Get(url);
unityGetRequest.request.timeout = timeout;
if (formData != null)
{
foreach (var header in formData.headers)
{
unityGetRequest.request.SetRequestHeader(header.Key, header.Value);
}
}
unityGetRequest.request.SendWebRequest();
return unityGetRequest;
}
}
class UnityPostRequest : IUnityWebRequest
{
UnityWebRequest request;
bool IUnityWebRequest.isDone => request.isDone;
float IUnityWebRequest.Progress => request.uploadProgress;
UnityWebRequest IUnityWebRequest.unityWebRequest => request;
public static IUnityWebRequest Create(string url, WWWForm formData, int timeout)
{
UnityPostRequest unityPostRequest = new UnityPostRequest();
unityPostRequest.request = UnityWebRequest.Post(url, formData);
unityPostRequest.request.timeout = timeout;
unityPostRequest.request.SendWebRequest();
return unityPostRequest;
}
}
}