.net Parallel.Foreach的Continue和Break和Return;

本文介绍了如何在C#中使用Parallel.ForEach结合ParallelLoopState来控制并行循环的行为,包括如何提前终止迭代以及如何正确地释放资源。
部署运行你感兴趣的模型镜像

在Foreach的时候需要多加一个ParallelLoopState

var parallelOption = new ParallelOptions() { MaxDegreeOfParallelism = 6 };

 Parallel.ForEach(As, parallelOption, (A,ParallelLoopState) =>

{

if(needContinue){

  ParallelLoopState.Break();//告诉CPU之后的迭代不需要执行,如0-1000的判断,从100开始break,则100之前的任然执行,从101开始到1000都不需要执行了
                return;
//不加return,可能会发生该进程资源未释放。

}


}


 Parallel.ForEach(As, parallelOption, (AParallelLoopState) =>
{

if(needBreak){

  ParallelLoopState.Stop();//告诉CPU放弃整个迭代
                return;
//不加return,可能会发生该进程资源未释放。

}

如果需要像For的Continue一样,则直接使用Return



}


您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

using System; using System.Buffers; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; public class DownloadService : IDisposable { private readonly HttpClient _httpClient; private CancellationTokenSource _cts = new(); private bool _isPaused; private readonly ConcurrentDictionary<string, FileDownloadState> _downloadStates = new(); private long _totalBytesRead; private long _totalSize; private readonly ConcurrentDictionary<string, byte> _allTempFiles = new(); private readonly IConnectivity _connectivity; // 定义下载完成事件委托 public delegate void FileDownloadedHandler(string filename); public event FileDownloadedHandler OnFileDownloaded; // 新增重连状态标志 private bool _reconnectFlag; private bool _wasKickedOff; public DownloadService() { // 全局TCP/IP优化 ServicePointManager.DefaultConnectionLimit = 200; ServicePointManager.Expect100Continue = false; ServicePointManager.UseNagleAlgorithm = false; ServicePointManager.ReusePort = true; ServicePointManager.MaxServicePoints = 1000; _httpClient = new HttpClient(new SocketsHttpHandler { PooledConnectionLifetime = TimeSpan.FromMinutes(5), PooledConnectionIdleTimeout = TimeSpan.FromMinutes(2), MaxConnectionsPerServer = 50, UseProxy = false, AutomaticDecompression = DecompressionMethods.All }); _httpClient.DefaultRequestHeaders.AcceptEncoding.ParseAdd("gzip, deflate, br"); _httpClient.DefaultRequestVersion = HttpVersion.Version20; _httpClient.Timeout = TimeSpan.FromMinutes(30); _httpClient.DefaultRequestHeaders.ConnectionClose = false; _connectivity = Connectivity.Current; _connectivity.ConnectivityChanged += OnConnectivityChanged; } private void OnConnectivityChanged(object sender, ConnectivityChangedEventArgs e) { if (_wasKickedOff) return; if (e.NetworkAccess != NetworkAccess.Internet) { Pause(); } else if (_isPaused) { _reconnectFlag = true; Resume(); } } public async Task DownloadAllAsync( Dictionary<string, string> files, IProgress<DownloadProgressReport> progress, int maxDegreeOfParallelism = 8) { var options = new ParallelOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism, CancellationToken = _cts.Token }; _totalBytesRead = 0; int completedFiles = 0; await Parallel.ForEachAsync(files, options, async (file, ct) => { string fileName = file.Key; string url = file.Value; var savePath = Path.Combine(FileSystem.AppDataDirectory, fileName); var tempPath = Path.GetTempFileName(); _allTempFiles[tempPath] = 0; try { var state = new FileDownloadState(fileName, tempPath); _downloadStates[fileName] = state; long downloadedForFile = 0; if (File.Exists(tempPath)) { downloadedForFile = new FileInfo(tempPath).Length; } else if (File.Exists(savePath)) { downloadedForFile = new FileInfo(savePath).Length; } while (true) { try { using var headResponse = await _httpClient.SendAsync( new HttpRequestMessage(HttpMethod.Head, url), ct); var totalFileSize = headResponse.Content.Headers.ContentLength ?? 0; // 动态分块大小 (8-16MB) int chunkSize = Math.Max(8 * 1024 * 1024, (int)(totalFileSize / 8)); chunkSize = Math.Min(chunkSize, 16 * 1024 * 1024); var chunks = (int)Math.Ceiling((double)(totalFileSize - downloadedForFile) / chunkSize); await Parallel.ForEachAsync(Enumerable.Range(0, chunks), new ParallelOptions { MaxDegreeOfParallelism = 8 // 每个文件8线程 }, async (chunkIndex, ct) => { var start = downloadedForFile + chunkIndex * chunkSize; var end = Math.Min(start + chunkSize - 1, totalFileSize - 1); using var request = new HttpRequestMessage(HttpMethod.Get, url); request.Headers.Range = new RangeHeaderValue(start, end); using var response = await _httpClient.SendAsync( request, HttpCompletionOption.ResponseHeadersRead, ct); response.EnsureSuccessStatusCode(); // 使用1MB大缓冲区 var buffer = ArrayPool<byte>.Shared.Rent(1024 * 1024); try { using var contentStream = await response.Content.ReadAsStreamAsync(); using var fileStream = new FileStream( tempPath, FileMode.Append, FileAccess.Write, FileShare.Write, 1024 * 1024, FileOptions.Asynchronous | FileOptions.WriteThrough); int bytesRead; while ((bytesRead = await contentStream.ReadAsync(buffer, 0, buffer.Length, ct)) > 0) { await fileStream.WriteAsync(buffer, 0, bytesRead, ct); downloadedForFile += bytesRead; Interlocked.Add(ref _totalBytesRead, bytesRead); progress?.Report(new DownloadProgressReport { TotalFiles = files.Count, CompletedFiles = completedFiles, DownloadedBytes = _totalBytesRead, TotalSize = _totalSize, CurrentFileName = file.Key, CurrentProgress = (double)downloadedForFile / totalFileSize }); } } finally { ArrayPool<byte>.Shared.Return(buffer); } }); File.Move(tempPath, savePath, true); _allTempFiles.TryRemove(tempPath, out _); Interlocked.Increment(ref completedFiles); OnFileDownloaded?.Invoke(fileName); break; } catch (OperationCanceledException) { throw; } catch (Exception ex) when (ex is HttpRequestException || ex is IOException) { if (_wasKickedOff) throw; await Task.Delay(5000, ct); } } } catch (OperationCanceledException) { } catch (Exception ex) { if (ex.Message.Contains("踢下线")) _wasKickedOff = true; } finally { if (!File.Exists(savePath)) { SafeDeleteFile(tempPath); } _allTempFiles.TryRemove(tempPath, out _); _downloadStates.TryRemove(fileName, out _); progress?.Report(new DownloadProgressReport { TotalFiles = files.Count, CompletedFiles = completedFiles, DownloadedBytes = _totalBytesRead, TotalSize = _totalSize }); } }); } public void Pause() => _isPaused = true; public void Resume() => _isPaused = false; public void Cancel() { _cts.Cancel(); foreach (var tempPath in _allTempFiles.Keys) { SafeDeleteFile(tempPath); } _allTempFiles.Clear(); _downloadStates.Clear(); _cts = new CancellationTokenSource(); _isPaused = false; _reconnectFlag = false; _wasKickedOff = false; _totalBytesRead = 0; } private void SafeDeleteFile(string path) { try { if (File.Exists(path)) File.Delete(path); } catch { // 忽略删除错误 } } public void Dispose() => _httpClient?.Dispose(); } public class DownloadProgressReport { public int TotalFiles { get; set; } public int CompletedFiles { get; set; } public int PrecalculatedFiles { get; set; } public long DownloadedBytes { get; set; } public long TotalSize { get; set; } public string CurrentFileName { get; set; } public double CurrentProgress { get; set; } public double OverallProgress => TotalSize > 0 ? (double)DownloadedBytes / TotalSize : 0; public int FileProgress => TotalFiles > 0 ? (CompletedFiles * 100) / TotalFiles : 0; } public class FileDownloadState { public string FileName { get; } public string TempPath { get; } public long DownloadedBytes { get; set; } public long TotalSize { get; set; } public double Progress => TotalSize > 0 ? (double)DownloadedBytes / TotalSize : 0; public FileDownloadState(string fileName, string tempPath) { FileName = fileName; TempPath = tempPath; } } 这段代码为什么下载成功后也写入缓存路径了,但是系统去读取路径时,无法读取,("/data/user/0/com.companyname.aitoy/files/theater02.mp4")这是路劲,确定手机是支持写入的,是代码的问题
最新发布
09-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值