C# 使用SSH.NET和WPF MVVM进行并行文件上载的进度条
我正在尝试构建一个WPF应用程序,它使用SSH.NET在服务器上并行上传多个文件,并为每个文件显示一个进度条 在视图中,我有以下数据网格:C# 使用SSH.NET和WPF MVVM进行并行文件上载的进度条,c#,wpf,progress-bar,ssh.net,C#,Wpf,Progress Bar,Ssh.net,我正在尝试构建一个WPF应用程序,它使用SSH.NET在服务器上并行上传多个文件,并为每个文件显示一个进度条 在视图中,我有以下数据网格: <DataGrid AlternatingRowBackground="LightGray" AutoGenerateColumns="False" CanUserAddRows="False"
<DataGrid
AlternatingRowBackground="LightGray"
AutoGenerateColumns="False"
CanUserAddRows="False"
CanUserDeleteRows="False"
IsReadOnly="True"
ItemsSource="{Binding Files, Mode=TwoWay}"
SelectedItem="{Binding SelectedFile, Mode=OneWayToSource}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=DisplayName}" Header="File" />
<DataGridTextColumn Binding="{Binding Path=FileSize}" Header="Size" />
<DataGridTextColumn Binding="{Binding Path=IsUploaded, Mode=OneWay}" Header="Uploaded" />
<DataGridTextColumn Binding="{Binding Path=IsUploading, Mode=OneWay}" Header="Uploading" />
<DataGridTemplateColumn Header="Progress">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<ProgressBar
Width="300"
Height="10"
Maximum="{Binding FileSize}"
Value="{Binding Path=SizeUploaded, Mode=OneWay}" />
<TextBlock
Margin="0,5,0,0"
HorizontalAlignment="Center"
Text="{Binding Path=PercentageCompleted, StringFormat={}{0}%}" />
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Start">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button cal:Message.Attach="UploadFile" Content="Start" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Stop">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button cal:Message.Attach="StopTransfer" Content="Stop" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Remove">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button cal:Message.Attach="RemoveFile" Content="Remove" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
要在服务器上上载文件,使用SSH.NET,我将执行以下操作:
private async Task UploadFileToServer(ConnectionModel connection, string fileName, string destinationPath)
{
if (!string.IsNullOrWhiteSpace(destinationPath))
{
await Task.Run(() =>
{
var currentUploadedFile = Files.FirstOrDefault(x => x.FullName == fileName);
currentUploadedFile.IsUploading = true;
try
{
_fileManager.UploadFile(connection, fileName, destinationPath);
currentUploadedFile.IsUploaded = true;
}
catch (Exception ex)
{
BroadCastErrorMessage(ex.Message);
IsConnectionTabExpanded = true;
}
finally
{
currentUploadedFile.IsUploading = false;
}
});
}
else
{
BroadCastErrorMessage("ERROR: You must enter a destination folder!");
IsConnectionTabExpanded = true;
}
}
FileManager调用的实际ssh.net库包含:
using (var fs = new FileStream(fileName, FileMode.Open))
{
fullFileName = fileName;
sftp.BufferSize = 4 * 1024;
sftp.UploadFile(fs, Path.GetFileName(fileName), true, uploadCallback: UpdateProgresBar);
OnFileUploadedSuccess($@"Successfully uploaded {fileName} in {path}.");
status = FileRenamedStatus.Uploaded;
}
并引发具有上载大小的事件:
private void UpdateProgresBar(ulong uploaded)
{
OnFileUploading(uploaded);
}
protected void OnFileUploading(ulong uploaded)
{
FileUploading?.Invoke(this, new UploadingEventArgs(new UploadedFile
{
SizeUploaded = (int)uploaded,
FullName = fullFileName
}));
}
在ViewModel中,我正在侦听事件并更新进度条:
private void OnUploading(object sender, UploadingEventArgs e)
{
foreach (var item in Files.ToList())
{
if (item.FullName == e.UploadedFile.FullName)
{
item.SizeUploaded = e.UploadedFile.SizeUploaded;
var percentage = (double)e.UploadedFile.SizeUploaded / item.FileSize;
item.PercentageCompleted = Math.Round(percentage * 100, 2);
}
}
}
我的问题是,当我开始第二次文件传输时,第一次传输的进度条会停止,第二次传输的进度条会发疯,显示随机值,增加或减少。我猜第一个文件的进度也在增加
不知何故,我无法区分每个进度条的进度
我做错了什么?我不确定这是否是正确的修复方法,但似乎每次调用
UploadFileToServer()
时都从IoC(使用Caliburn.Micro)获取一个新的\u fileManager
实例解决了progressbar问题:
var-manager=IoC.Get();
manager.onuploding+=onuploding代码>
private void UpdateProgresBar(ulong uploaded)
{
OnFileUploading(uploaded);
}
protected void OnFileUploading(ulong uploaded)
{
FileUploading?.Invoke(this, new UploadingEventArgs(new UploadedFile
{
SizeUploaded = (int)uploaded,
FullName = fullFileName
}));
}
private void OnUploading(object sender, UploadingEventArgs e)
{
foreach (var item in Files.ToList())
{
if (item.FullName == e.UploadedFile.FullName)
{
item.SizeUploaded = e.UploadedFile.SizeUploaded;
var percentage = (double)e.UploadedFile.SizeUploaded / item.FileSize;
item.PercentageCompleted = Math.Round(percentage * 100, 2);
}
}
}