i have class that reads data from a large file (1GB) using a fixed buffersize and writes it in an array. i want to let the user cancels the process whenever they want to. how can i stop the loop from outside of the loop.( i think using events would be a good idea but dont know how to do it)
note: i have a form that will send the cancellation request.
for (int i = 0; i < fileContent.Length; i )
{
try
{
fileContent[i] = br.ReadInt16();
}
catch (EndOfStreamException)
{
loadflag = 1;
contentSize = i;
break;
}
}
for (int k = 0; k < contentSize; k = ReSampleRate)
{
try
{
convertedData[(count * fileContent.Length / ReSampleRate) j] = fileContent[k];
j ;
}
catch (IndexOutOfRangeException)
{
MessageBox.Show("could not load the file completely");
goto lable;
}
catch
{
MessageBox.Show("something went wrong");
}
}
if (loadflag == 1)
{
break;
}
}
CodePudding user response:
Make your method take a CancellationToken
. Change your loop so it calls cancellationToken.ThrowIfCancellationRequested()
each iteration. Ensure your caller catches the resulting OperationCancelledException. The form should create a CancellationTokenSource
with a Token property that can be given to your method, and a cancel method that can be called by your form.
Note that your method need to be run on a background thread for all of this to work, typically using Task.Run
, but this will require you to move your messageboxes, and any other code that updates the UI, outside the method to be cancelled. A possible exception to this might be if you have an async method that mostly awaits IO to complete.
Example:
private CancellationTokenSource cts = new CancellationTokenSource();;
public async void OnButtonPress(){
try{
cts = new CancellationTokenSource();
await Task.Run(() => OnBackgroundThread(cts.Token));
void OnBackgroundThread(CancellationToken cancel){
foreach(var item in MyItemsToProcess){
cancel.ThrowIfCancellationRequested();
// Process item
}
}
catch(OperationCancelledException){
// do nothing
}
// Handle other errors
}
}
public void OnCancelPress(){
cts.Cancel();
}
Another variant is to check the cancellationToken.IsCancellationRequested
property and return normally. But this makes it impossible for the caller to determine if the loop completed or not, at best it can check if the token was cancelled.
If you are looking for some way to cancel the loop without any changes to it you are out of luck. There are no good way to abort a running thread non-cooperativly.