I am trying to build a function that searches a directory for files and adds them to an ObservableCollection
.
This task should run asynchronously so that the UI remains responsive and stops searching at any time when the method is executed again. So that the ObservableCollection
is cleared and the search starts again.
My problem is that I don't know how and when exactly to cancel the CancellationTokenSource in the same method when the task is still running.
Also, I don't know exactly how to use Async and Await on the function since it is split between three methods.
Right now it looks like this:
Search Function:
CancellationTokenSource _tokenSource;
public async void SearchAsync()
{
Files.Clear();
FileCount = 0;
// Cancels Task if its running
if(_tokenSource != null)
{
_tokenSource.Cancel(); (throws Error right here. Task already disposed)
}
// Create new Cancellation Token
_tokenSource = new CancellationTokenSource();
CancellationToken token = _tokenSource.Token;
try
{
//Starts Task
await Task.Run(() => FindFiles(token));
}
catch (OperationCanceledException ex)
{
//When Canceled
MessageBox.Show("Test", "Test");
}
finally
{
//When finished
_tokenSource.Dispose();
}
}
Find Files:
private async Task FindFiles(CancellationToken token)
{
foreach (string filePath in Directory.EnumerateFiles(MainPath, "*.*", searchOption))
{
await AddFileAsync(filePath);
FileCount++;
if (token.IsCancellationRequested)
{
Files.Clear();
FileCount = 0;
token.ThrowIfCancellationRequested();
}
}
}
Add Files to ObservableCollection:
I put this into a own method because it's called multiple times in LoadFiles()
. I just simplified it.
public ObservableCollection<FileModel> Files { get; set; }
private async Task AddFileAsync(string filePath)
{
await Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
FileModel file = new()
{
FileName = Path.GetFileName(filePath),
FilePath = filePath
};
Files.Add(file);
}));
}