I'm trying to evolve the code from this Progress bar tutorial with a cancel button but so far without success:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private CancellationTokenSource cts;
private void Calculate(int i)
{
Math.Pow(i, i);
}
public void DoWork(IProgress<int> progress, CancellationToken cancelToken)
{
for (int j = 0; j < 100000; j++)
{
if (cancelToken.IsCancellationRequested)
cancelToken.ThrowIfCancellationRequested();
Calculate(j);
progress?.Report((1 + j) * 100 / 100000);
}
}
private async void run_Click(object sender, EventArgs e)
{
cts = new CancellationTokenSource();
var cancelToken = cts.Token;
progressBar.Maximum = 100;
progressBar.Step = 1;
var progress = new Progress<int>(v => progressBar.Value = v);
try
{
await Task.Run(() => { DoWork(progress, cancelToken); }, cts.Token);
}
catch (OperationCanceledException ex)
{
Console.WriteLine($"{nameof(OperationCanceledException)} thrown with message: {ex.Message}");
}
finally
{
cts = null;
}
}
private void cancel_Click(object sender, EventArgs e)
{
Console.WriteLine("Cancel");
cts?.Cancel();
}
}
After clicking run, the UI froze and I can't click on the Cancel button. I've read those blogs:
- https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
- Accessing UI controls in Task.Run with async/await on WinForms
- https://devblogs.microsoft.com/csharpfaq/parallel-programming-task-cancellation/
- https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/fine-tuning-your-async-application
But couldn't find an answer, I have also tried this variation:
await Task.Factory.StartNew(() => { DoWork(progress, cancelToken); }, cts.Token);
And it didn't work, can't click on the cancel button during the loading. Any idea? (I'm sure it's ridiculously simple).