I used IProgress
and Task
to upload asynchronously and display the upload progress, supporting asynchronous cancellation.
Create the inner function UploadFileViaSftp and call it in the outer function via await Task.Run(() => UploadFileViaSftp(…)) . The outer function already has a catch block, but the OperationCanceledException error still occurs.
private async void btn_save_Click(object sender, EventArgs e)
{
try
{
cancellationTokenSource = new CancellationTokenSource();
var token = cancellationTokenSource.Token;
progressForm = new ProgressForm(() =>
{
cancellationTokenSource.Cancel();
});
progressForm.Show();
var progressIndicator = new Progress<int>(percent =>
{
progressForm.UpdateProgress(percent);
});
await Task.Run(() => UploadFileViaSftp(client, token, progressIndicator, fileStream, pictureStream, remoteDirectory + "/" + fileName));
MessageBox.Show("success");
}
catch (OperationCanceledException)
{
MessageBox.Show("canceld");
}
catch (Exception ex)
{
MessageBox.Show("error" + ex.Message);
}
finally
{
}
}
private void UploadFileViaSftp(SftpClient sftpClient, CancellationToken cancellationToken, IProgress<int> progress, FileStream fileStream, FileStream picStream, string remoteFilePath)
{
bool isFileStartUploaded = false;
bool isPicStartUploaded = false;
try
{
if (!sftpClient.IsConnected)
{
sftpClient.Connect();
}
if (fileStream.CanRead && picStream.CanRead)
{
long totalBytes = fileStream.Length + picStream.Length;
long uploadedBytes = 0;
byte[] buffer = new byte[8192];
int bytesRead;
using (var uploadStream = sftpClient.OpenWrite(remoteFilePath))
{
isFileStartUploaded = true;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
cancellationToken.ThrowIfCancellationRequested();
uploadStream.Write(buffer, 0, bytesRead);
uploadedBytes += bytesRead;
int percentComplete = (int)((double)uploadedBytes / totalBytes * 100);
progress.Report(percentComplete);
}
}
using (var uploadPicStream = sftpClient.OpenWrite(Path.ChangeExtension(remoteFilePath, ".png")))
{
isPicStartUploaded = true;
while ((bytesRead = picStream.Read(buffer, 0, buffer.Length)) > 0)
{
cancellationToken.ThrowIfCancellationRequested();
uploadPicStream.Write(buffer, 0, bytesRead);
uploadedBytes += bytesRead;
int percentComplete = (int)((double)uploadedBytes / totalBytes * 100);
progress.Report(percentComplete);
}
}
isPicStartUploaded = true;
}
else
{
MessageBox.Show("permisson denied");
}
}
catch (OperationCanceledException)
{
if (!sftpClient.IsConnected)
{
sftpClient.Connect();
}
if (isFileStartUploaded && sftpClient.Exists(remoteFilePath))
{
sftpClient.DeleteFile(remoteFilePath);
}
string remotePicPath = Path.ChangeExtension(remoteFilePath, ".png");
if (isPicStartUploaded && sftpClient.Exists(remotePicPath))
{
sftpClient.DeleteFile(remotePicPath);
}
string remoteDirectory = Path.GetDirectoryName(remoteFilePath);
if (sftpClient.Exists(remoteDirectory) && sftpClient.ListDirectory(remoteDirectory).Count() == 0)
{
sftpClient.DeleteDirectory(remoteDirectory);
}
throw;
}
catch (Exception)
{
throw;
}
}
What can I do when inner function UploadFileViaSftp
catch OperationCancelException and throw to outer function again for further processing
3