Skip to content

Instantly share code, notes, and snippets.

@nekomimi-daimao
Created November 1, 2023 17:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nekomimi-daimao/197f403a357ca0d7710732b5fd9e9175 to your computer and use it in GitHub Desktop.
Save nekomimi-daimao/197f403a357ca0d7710732b5fd9e9175 to your computer and use it in GitHub Desktop.
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