не может нажать на кнопку отмены во время загрузки. Есть идеи? (Я уверен, что это до смешного просто).
Как уже отмечали другие, вашему DoWork
нужно проделать дополнительную работу, прежде чем прерывать поток пользовательского интерфейса другим обновлением. Итак, что-то вроде этого должно работать:
private void Calculate(int i)
{
for (int j = 0; j != 10000; ++j)
Math.Pow(i, i);
}
В настоящее время поток пользовательского интерфейса заполнен обновлениями прогресса, поэтому у него нет времени на ответ пользователя.
Если ваш реальный Мировой код нелегко разбить на более крупные куски, вы можете использовать реализацию IProgress<T>
с регулированием скорости, такую как , которую я написал при обновлении моей книги :
public static class ObservableProgress
{
public static (IObservable<T> Observable, IProgress<T> Progress) CreateForUi<T>(TimeSpan? sampleInterval = null)
{
var (observable, progress) = Create<T>();
observable = observable.Sample(sampleInterval ?? TimeSpan.FromMilliseconds(100))
.ObserveOn(SynchronizationContext.Current);
return (observable, progress);
}
public static (IObservable<T> Observable, IProgress<T> Progress) Create<T>()
{
var progress = new EventProgress<T>();
var observable = Observable.FromEvent<T>(handler => progress.OnReport += handler, handler => progress.OnReport -= handler);
return (observable, progress);
}
private sealed class EventProgress<T> : IProgress<T>
{
public event Action<T> OnReport;
void IProgress<T>.Report(T value) => OnReport?.Invoke(value);
}
}
Использование:
private async void run_Click(object sender, EventArgs e)
{
cts = new CancellationTokenSource();
var cancelToken = cts.Token;
progressBar.Maximum = 100;
progressBar.Step = 1;
var (observable, progress) = ObservableProgress.CreateForUi<int>();
try
{
using (observable.Subscribe(v => progressBar.Value = v))
await Task.Run(() => { DoWork(progress, cancelToken); }, cts.Token);
}
catch (OperationCanceledException ex)
{
Console.WriteLine($"{nameof(OperationCanceledException)} thrown with message: {ex.Message}");
}
finally
{
cts = null;
}
}
Регулирование скорости IProgress<T>
отбрасывает дополнительные обновления прогресса, отправляя только одно обновление прогресса каждые 100 мс в поток пользовательского интерфейса, который он должен легко обрабатывать и реагировать на него. взаимодействие с пользователем.