wpf - Task cancellation: while loop not exited properly when ThrowIfCancellationRequested() is called -


i've developed small project (using mvvm) functionality upload file ftp-server.

the user can view uploading progress: percentage completed shown user vm.busycontent, property in viewmodel bound ui element in view.

here code reading file , uploading via ftp (which part of task 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

i using wpf extended toolkit 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();     } } 

the cancel function works vm.busycontent equals

  • ((int)progress).tostring()
  • canceled in uploadftpcommand

when pressing cancel button, while loop should exited , user should see message in catch (operationcanceledexception). ideas how solve this?

notes

  • i using .net 4.0
  • this program part of larger project, includes multipe tasks should executed in synchronous manner. that's why using task.start() , task.wait() methods.

edit problem still remains

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();     } } 

}

you may have issue relating how you've set code. without going through every line of it, it's difficult tell. more point:

when pressing cancel button, while loop should exited , user should see message in catch (operationcanceledexception).

this shows how exit while loop , throw exception can catch. note test asserts taskcanceledexception right in catching operationcanceledexception.

using system.threading.tasks; using system.io; using system.threading;  using nunit.framework;  namespace cancellationtests {      [testfixture]     public class whilecancellation {          [test]         public void while_loop_is_canceled_when_cancel_is_requested() {             var inputfile = new fileinfo("somebigfile.txt");             var outputfile = new fileinfo("outputfile.txt");             var cts = new cancellationtokensource();              cts.cancel();              assert.throwsasync<taskcanceledexception>(() => thewhileloop(inputfile, outputfile, cts.token));         }          private async task thewhileloop(fileinfo inputfile, fileinfo outputfile, cancellationtoken token) {              using (var inputstream = inputfile.openread())             using (var outputstream = outputfile.openwrite()) {                 var buffer = new byte[1024 * 1024];                 var totalreadbytescount = 0;                 var readbytescount = 0;                  while ((readbytescount = await inputstream.readasync(buffer, 0, buffer.length, token)) > 0) {                                         await outputstream.writeasync(buffer, 0, readbytescount, token);                     token.throwifcancellationrequested();                     totalreadbytescount += readbytescount;                     var progress = totalreadbytescount * 100.0 / inputstream.length;                     vm.busycontent = ((int)progress).tostring();                 }             }         }                  private static class vm {             public static string busycontent { get; set; }         }     }     } 

hopefully gets on right track.


Comments

Popular posts from this blog

javascript - Clear button on addentry page doesn't work -

c# - Selenium Authentication Popup preventing driver close or quit -

tensorflow when input_data MNIST_data , zlib.error: Error -3 while decompressing: invalid block type -