J'ai développé un petit projet (en utilisant MVVM) avec des fonctionnalités permettant de télécharger un fichier sur un serveur FTP.Annulation de tâche: lorsque la boucle n'est pas fermée correctement lorsque ThrowIfCancellationRequested() est appelée
L'utilisateur peut voir la progression du téléchargement: le pourcentage complété est affiché à l'utilisateur par vm.Busycontent, qui est une propriété dans mon viewmodel lié à un élément de l'interface utilisateur dans ma vue.
Voici le code pour lire le fichier et le téléchargement via FTP (qui fait partie du Groupe vm.FtpUploadTask)
using (FileStream inputStream = File.OpenRead(file))
{
using (outputStream = request.GetRequestStream())
{
var buffer = new byte[1024 * 1024];
int totalReadBytesCount = 0;
int readBytesCount;
while ((readBytesCount = inputStream.Read(buffer, 0, buffer.Length)) > 0 && (!vm.Token.IsCancellationRequested))
{
vm.Token.ThrowIfCancellationRequested();
outputStream.Write(buffer, 0, readBytesCount);
totalReadBytesCount += readBytesCount;
var progress = totalReadBytesCount * 100.0/inputStream.Length;
vm.BusyContent = ((int)progress).ToString();
}
}
}
MainWindow.xaml
J'utilise boîte à outils WPF étendu BusyIndicator
<xctk:BusyIndicator IsBusy='{Binding IsBusy}'>
<xctk:BusyIndicator.BusyContentTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text='{Binding Path=DataContext.BusyContent,
RelativeSource={RelativeSource AncestorType={x:Type Window}}}' />
</StackPanel>
</DataTemplate>
</xctk:BusyIndicator.BusyContentTemplate>
</xctk:BusyIndicator>
UploadToFTPCommand.cs
try
{
vm.FtpUploadTask = new Task(() => FTPUpload(file), vm.Token);
vm.FtpUploadTask.Start();
vm.FtpUploadTask.Wait(vm.Token);
vm.BusyContent = "upload done!";
}
catch (OperationCanceledException)
{
vm.BusyContent = "Canceled";
}
CancelCommand.cs
public class CancelCommand : ICommand
{
public void Execute(object parameter)
{
vm.TokenSource.Cancel();
}
}
Les travaux de fonction d'annulation mais parfois vm.Busycontent égale à
- ((int) progrès) .ToString()
- annulé dans uploadftpc
Lorsque vous appuyez sur le bouton Annuler, la boucle while doit être fermée et l'utilisateur doit uniquement voir le message dans la capture (OperationCanceledException). Des idées pour résoudre ce problème?
Remarques
- J'utilise .NET 4.0
- Ce programme est une partie d'un projet plus vaste, qui comprend les tâches multipe qui doivent être exécutées de manière synchrone. C'est pourquoi j'utilise les méthodes Task.Start() et Task.Wait().
Modifier problème reste
using (FileStream inputStream = File.OpenRead(file))
{
using (outputStream = request.GetRequestStream())
{
var buffer = new byte[1024 * 1024];
int totalReadBytesCount = 0;
int readBytesCount;
while ((readBytesCount = inputStream.Read(buffer, 0, buffer.Length)) > 0)
{
if (vm.Token.IsCancellationRequested)
{
break;
}
outputStream.Write(buffer, 0, readBytesCount);
totalReadBytesCount += readBytesCount;
var progress = totalReadBytesCount * 100.0/inputStream.Length;
vm.BusyContent = ((int)progress).ToString();
}
if (vm.Token.IsCancellationRequested)
{
inputStream.Close();
outputStream.Close();
vm.Token.ThrowIfCancellationRequested();
}
}
}
Vous vérifiez 'Token.IsCancellationRequested' et vous quittez la boucle avant d'exécuter 'ThrowIfCancellationRequested()'. – JSteward
C'est beaucoup de code, pourriez-vous poster un [mcve]? – svick
@svick Je modifie ma question pour réduire la quantité de code – BertAR