Click here to Skip to main content
15,892,927 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
My source code performs a task and it does import txt files. I need to give the option to cancel this process when the user wants to. I tried several times to cancel the action but I can't.

What I have tried:

Task taskImport = null;

private void Menu_Load(object sender, EventArgs e)
        {
            taskImport = new Task(Readtxt);//Readtxt is a method
        }

private void BtnImport_Click(object sender, EventArgs e)
        {
            taskImport.Start();
        }
Posted
Updated 26-Sep-19 13:22pm
v2

Something like this:
C#
CancellationTokenSource _cts = null;

private void BtnImoprt_Click(object sender, EventArgs e)
{
    CancellationTokenSource newSource = new CancellationTokenSource();
    CancellationTokenSource oldSource = Interlocked.Exchange(ref _cts, newSource);
    if (oldSource != null)
    {
        oldSource.Cancel();
        oldSource.Dispose();
    }
    
    Task.Run(() => Readtxt(newSource.Token), newSource.Token);
}

private void BtnCancel_Click(object sender, EventArgs e)
{
    CancellationTokenSource oldSource = Interlocked.Exchange(ref _cts, null);
    if (oldSource != null)
    {
        oldSource.Cancel();
        oldSource.Dispose();
    }
}

private async Task Readtxt(CancellationToken cancellationToken)
{
    // Pass the cancellation token to any async methods that support it.
    // Regularly check its IsCancellationRequested property, or call its ThrowIfCancellationRequested method.
}
Cancellation in Managed Threads | Microsoft Docs[^]

How effective this will be will depend on the methods you're using within the Readtxt method.
 
Share this answer
 
Comments
Member 11426986 26-Sep-19 7:36am    
This is method Readtxt

void Readtxt()
{
string ccte = txtFolderCTE.Text;
string folder = null;
foreach (var fileSystem in Directory.GetFiles(ccte, "*.xml", SearchOption.AllDirectories))
{
FileInfo fi = new FileInfo(fileSystem);
caminho = fi.FullName;

try
{
DirectXML dir = new DirectXML();
dir.direcionarXML(folder, "");
}
catch (Exception m)
{
registerLog(m.Message, folder);
}
}
}
Richard Deeming 26-Sep-19 7:48am    
That method makes no sense. Why are you enumerating over every XML file in the folder, when you're not doing anything with those files? You're just calling the same method with the same parameters over and over again.
Member 11426986 26-Sep-19 8:09am    
No "DirectXML dir = new DirectXML ();
dir.direcionarXML(folder, ""); ", it will read the XML files and save the collected information to a database.
Richard Deeming 26-Sep-19 8:12am    
Nowhere in the code that you've shown are you using the loop variable. You're looping over every XML file in the folder, and calling the same method with the same parameters once for each file.

Nothing in your try..catch block uses fileSystem, fi, or caminho.

The loop makes no sense.
Member 11426986 26-Sep-19 8:32am    
In foreach it will fetch all the XML files from the directory you entered in the ccte variable. This will take the full path of each XML file and pass it to the class that will read the XML.
Sorry, there was an editing error.

FileInfo fi = new FileInfo (fileSystem);
folder = fi.FullName;

try
{
DirectXML dir = new DirectXML ();
dir.directXML (folder, "");
}
catch (Exception m)
{
registerLog (m.Message, folder);
}

You don't want to be creating new Tasks and managing them directly, it's better to call a method that returns a Task.
FileStream.ReadAsync() returns a Task, supports the asynchronous reading of data and it can be cancelled.
You can use it like this.

C#
private async Task<string>ReadFileAsync(string filePath,CancellationToken token)
 {

   byte[] byteArray;
   FileStream fileStream = null;
   try
      {
       fileStream = File.Open(filePath, FileMode.Open);
       byteArray = new byte[fileStream.Length];
       //this method call throws an OperationCancelledException if cancelled
       //At this point control is returned to the UI thread
       //until the method completes
       await fileStream.ReadAsync(byteArray, 0, (int)fileStream.Length, token);
       string text=Encoding.ASCII.GetString(byteArray);
       return text;
      }

   finally
      {
        if (fileStream != null) fileStream.Dispose();            }
      }

You can start the loading of data in the start button click handler.
C#
private CancellationTokenSource cts;

private async void Start(object sender, RoutedEventArgs e)
 {
   List<string> texts = new List<string>();
   string filename = @"c:\Temp\Io.txt";
   //disable the start button and enable the cancel button
   cts = new CancellationTokenSource();
   //Or, to test the cancellation process,
   //make cts cancel itself after 20 millisecs
   //cts = new CancellationTokenSource(20);
   try
     {
      //simulate reading 100 files
      for (int i = 0; i < 100; i++)
       {
        //pass in the cancellation token to the file read method
        string text = await ReadFileAsync(filename, cts.Token);
        texts.Add(text);
       }
      }
    catch (OperationCanceledException )
       {
         //do something with the cancelled data
         texts.Clear();
       }

          //......
   }

Use the cancel button click handler to cancel the file reads.The CancellationTokenSource is spent after cancellation and cannot be reused.
C#
private void Cancel(object sender, RoutedEventArgs e)
{

    if (cts != null) cts.Cancel();

}

 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900