FieldWorkClient/ViewModel/Send/DownViewModel.cs

261 lines
7.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System.Collections.Concurrent;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Windows.Data;
using System.Windows.Input;
using HeBianGu.Base.WpfBase;
using HeBianGu.Service.Mvc;
using Hopetry.Models;
using Hopetry.Provider;
using Hopetry.Services;
using Newtonsoft.Json;
using SqlSugar;
namespace Hopetry.ViewModel.Send;
[ViewModel("Down")]
public class DownViewModel : MvcViewModelBase
{
private readonly MinioService _minioService;
public RelayCommand<MinioDownloadTask> OpenDownItemFolder { get; set; }
private readonly ConcurrentQueue<MinioDownloadTask> _taskQueue = new();
private SemaphoreSlim _concurrencySemaphore;
private CancellationTokenSource _processingCts = new();
public int count { get; set; }
private SemaphoreSlim _semaphore;
private readonly ReaderWriterLockSlim _lock = new();
/// <summary>
/// 全部任务动态标题
/// </summary>
private string _allTaskHeader;
public string AllTaskHeader
{
get => _allTaskHeader;
set
{
_allTaskHeader = value;
RaisePropertyChanged();
}
}
private string _runningTaskHeader;
public string RunningTaskHeader
{
get => _runningTaskHeader;
set
{
_runningTaskHeader = value;
RaisePropertyChanged();
}
}
private string _finishedTaskHeader;
public string FinishedTaskHeader
{
get => _finishedTaskHeader;
set
{
_finishedTaskHeader = value;
RaisePropertyChanged();
}
}
// 绑定属性
public ObservableCollection<MinioDownloadTask> AllTasks { get; set; } = new();
public ICollectionView RunningTasksView { get; set; }
public ICollectionView FinishedTasksView { get; set; }
private int _maxConcurrent = 3;
public int MaxConcurrent
{
get => _maxConcurrent;
set
{
if (value < 1) value = 1;
if (_maxConcurrent == value) return;
_maxConcurrent = value;
//AdjustConcurrency();
RaisePropertyChanged();
}
}
private int _runningTasks;
public int RunningTasks
{
get => _runningTasks;
private set
{
_runningTasks = value;
RaisePropertyChanged();
}
}
// 命令
public ICommand AddTaskCommand { get; set; }
public ICommand ClearFinishedCommand { get; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="minioService"></param>
public DownViewModel(MinioService minioService, SemaphoreSlim semaphore)
{
_minioService = minioService;
_semaphore = semaphore;
Console.WriteLine("初始化DownViewModel");
using var client = SqlSugarConfig.GetSqlSugarScope();
var data = client.Ado.SqlQuery<MinioDownloadTask>($"select * from download_task");
//DownItems = new ObservableCollection<DownItem>(data);
AllTasks = new ObservableCollection<MinioDownloadTask>(data);
AllTaskHeader = $"全部({AllTasks.Count}";
//Console.WriteLine(JsonConvert.SerializeObject(data));
OpenDownItemFolder = new RelayCommand<MinioDownloadTask>(DoOpenDownItemFolder);
// 命令初始化
// AddTaskCommand = new RelayCommand(AddTask, CanAddTask);
// 修正:使用 CollectionViewSource 确保通知
var cvsRunning = new CollectionViewSource { Source = AllTasks };
cvsRunning.Filter += (s, e) =>
{
var b = ((MinioDownloadTask)e.Item).Status is "下载中" or "等待中" or "已暂停";
e.Accepted = b;
};
RunningTasksView = cvsRunning.View;
var cvsFinished = new CollectionViewSource { Source = AllTasks };
cvsFinished.Filter += (s, e) =>
{
var b = ((MinioDownloadTask)e.Item).Status == "已完成";
e.Accepted = b;
};
FinishedTasksView = cvsFinished.View;
if (FinishedTasksView is ListCollectionView finishListView)
{
FinishedTaskHeader = $"已完成({finishListView.Count}";
}
if (RunningTasksView is ListCollectionView runningListView)
{
RunningTaskHeader = $"下载中({runningListView.Count}";
}
// 关键:订阅数据源变更事件,强制视图刷新
AllTasks.CollectionChanged += (s, e) =>
{
RunningTasksView.Refresh();
FinishedTasksView.Refresh();
};
ClearFinishedCommand = new CustomCommand(() =>
{
// todo 删除已完成的下载记录
});
// 启动任务处理线程
_semaphore = new SemaphoreSlim(_maxConcurrent);
// 启动任务处理线程
_concurrencySemaphore = new SemaphoreSlim(_maxConcurrent);
new Thread(ProcessTasksLoop) { IsBackground = true }.Start();
AddTaskCommand = new ActionCommand(AddTask);
}
private void ProcessTasksLoop()
{
while (!_processingCts.IsCancellationRequested)
{
_semaphore.WaitAsync();
// 按当前并发数启动任务
for (int i = 0; i < _maxConcurrent; i++)
{
if (_taskQueue.TryDequeue(out var task))
{
// 启动新线程执行下载任务
_ = Task.Run(() => ExecuteTaskAsync(task));
}
}
Thread.Sleep(100);
}
}
private void AddTask()
{
string[] objectKeys = { "demo/06.mp4", "demo/07.mp4", "demo/08.mp4", "demo/10.mp4" };
var task = new MinioDownloadTask(_minioService, "demo", objectKeys[count++]);
using var client = SqlSugarConfig.GetSqlSugarScope();
client.Insertable(task).ExecuteCommandIdentityIntoEntity();
AllTasks.Add(task);
_taskQueue.Enqueue(task);
}
private async Task ExecuteTaskAsync(MinioDownloadTask task)
{
try
{
await task.StartDownload();
// todo 任务完成下载
}
finally
{
_semaphore.Release();
}
}
private void AdjustConcurrency()
{
lock (_concurrencySemaphore)
{
// 调整信号量容量
var delta = _maxConcurrent - _concurrencySemaphore.CurrentCount;
if (delta > 0)
{
for (int i = 0; i < delta; i++)
{
_concurrencySemaphore.Release();
}
}
}
}
public void DoOpenDownItemFolder(MinioDownloadTask para)
{
Console.WriteLine($"点击item值{JsonConvert.SerializeObject(para)}");
Process.Start("explorer.exe", para.FilePath);
}
public void DoCancelDownItem(MinioDownloadTask item)
{
Console.WriteLine("取消下载");
// todo 实现取消下载
}
public void DoPauseDownItem(MinioDownloadTask item)
{
Console.WriteLine("暂停下载");
// todo 实现暂停下载
}
protected override void Init()
{
}
protected override void Loaded(string args)
{
}
}