Created
November 1, 2023 17:24
-
-
Save nekomimi-daimao/197f403a357ca0d7710732b5fd9e9175 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Threading; | |
using System.Threading.Channels; | |
using System.Threading.Tasks; | |
using Cysharp.Threading.Tasks; | |
using UniRx; | |
using UnityEngine; | |
using UnityEngine.Networking; | |
using Channel = System.Threading.Channels.Channel; | |
public class ParallelDownload | |
{ | |
private void ParallelTry(IEnumerable<DownloadTask> tasks, CancellationToken token) | |
{ | |
var parallelOptions = new ParallelOptions | |
{ | |
MaxDegreeOfParallelism = 4, | |
CancellationToken = token, | |
}; | |
Parallel.ForEach(tasks, parallelOptions, Body); | |
} | |
private async void ChannelTry(IEnumerable<DownloadTask> tasks, CancellationToken token) | |
{ | |
var channel = Channel.CreateUnbounded<DownloadTask>(new UnboundedChannelOptions() | |
{ | |
SingleWriter = true, | |
}); | |
var channelWriter = channel.Writer; | |
foreach (var downloadTask in tasks) | |
{ | |
await channelWriter.WaitToWriteAsync(token).ConfigureAwait(false); | |
await channelWriter.WriteAsync(downloadTask, token).ConfigureAwait(false); | |
} | |
channelWriter.TryComplete(); | |
var parallelCount = 4; | |
for (var i = 0; i < parallelCount; i++) | |
{ | |
Loop(channel.Reader, token).Forget(); | |
} | |
} | |
private static async UniTaskVoid Loop( | |
System.Threading.Channels.ChannelReader<DownloadTask> reader, CancellationToken token) | |
{ | |
while (true) | |
{ | |
var waitToRead = await reader.WaitToReadAsync(token); | |
if (!waitToRead) | |
{ | |
break; | |
} | |
if (reader.TryRead(out var task)) | |
{ | |
await task.Download(); | |
} | |
} | |
} | |
private static async void Body(DownloadTask task) | |
{ | |
await task.Download(); | |
} | |
} | |
class DownloadTask | |
{ | |
private readonly UniTaskCompletionSource _completionSource = new(); | |
public UniTask Result => _completionSource.Task; | |
public Uri Uri; | |
public string Path; | |
public readonly FloatReactiveProperty Progress = new(); | |
public async UniTask Download() | |
{ | |
try | |
{ | |
var unityWebRequest = UnityWebRequest.Get(Uri); | |
unityWebRequest.downloadHandler = new DownloadHandlerFile(Path, false); | |
await unityWebRequest.SendWebRequest(); | |
_completionSource.TrySetResult(); | |
} | |
catch (Exception e) | |
{ | |
_completionSource.TrySetException(e); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment