| File: System\ComponentModel\BackgroundWorker.cs | Web Access |
| Project: src\runtime\src\libraries\System.ComponentModel.EventBasedAsync\src\System.ComponentModel.EventBasedAsync.csproj (System.ComponentModel.EventBasedAsync) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; namespace System.ComponentModel { public class BackgroundWorker : Component { // Private instance members private bool _canCancelWorker; private bool _workerReportsProgress; private bool _cancellationPending; private bool _isRunning; private AsyncOperation? _asyncOperation; private readonly SendOrPostCallback _operationCompleted; private readonly SendOrPostCallback _progressReporter; public BackgroundWorker() { _operationCompleted = new SendOrPostCallback(AsyncOperationCompleted!); _progressReporter = new SendOrPostCallback(ProgressReporter!); } private void AsyncOperationCompleted(object arg) { _isRunning = false; _cancellationPending = false; OnRunWorkerCompleted((RunWorkerCompletedEventArgs)arg); } public bool CancellationPending { get { return _cancellationPending; } } public void CancelAsync() { if (!WorkerSupportsCancellation) { throw new InvalidOperationException(SR.BackgroundWorker_WorkerDoesntSupportCancellation); } _cancellationPending = true; } public event DoWorkEventHandler? DoWork; public bool IsBusy { get { return _isRunning; } } protected virtual void OnDoWork(DoWorkEventArgs e) { DoWork?.Invoke(this, e); } protected virtual void OnRunWorkerCompleted(RunWorkerCompletedEventArgs e) { RunWorkerCompleted?.Invoke(this, e); } protected virtual void OnProgressChanged(ProgressChangedEventArgs e) { ProgressChanged?.Invoke(this, e); } public event ProgressChangedEventHandler? ProgressChanged; // Gets invoked through the AsyncOperation on the proper thread. private void ProgressReporter(object arg) { OnProgressChanged((ProgressChangedEventArgs)arg); } // Cause progress update to be posted through current AsyncOperation. public void ReportProgress(int percentProgress) { ReportProgress(percentProgress, null); } // Cause progress update to be posted through current AsyncOperation. public void ReportProgress(int percentProgress, object? userState) { if (!WorkerReportsProgress) { throw new InvalidOperationException(SR.BackgroundWorker_WorkerDoesntReportProgress); } ProgressChangedEventArgs args = new ProgressChangedEventArgs(percentProgress, userState); if (_asyncOperation != null) { _asyncOperation.Post(_progressReporter, args); } else { _progressReporter(args); } } public void RunWorkerAsync() { RunWorkerAsync(null); } public void RunWorkerAsync(object? argument) { if (_isRunning) { throw new InvalidOperationException(SR.BackgroundWorker_WorkerAlreadyRunning); } _isRunning = true; _cancellationPending = false; _asyncOperation = AsyncOperationManager.CreateOperation(null); Task.Factory.StartNew( WorkerThreadStart, argument, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default ); } public event RunWorkerCompletedEventHandler? RunWorkerCompleted; public bool WorkerReportsProgress { get { return _workerReportsProgress; } set { _workerReportsProgress = value; } } public bool WorkerSupportsCancellation { get { return _canCancelWorker; } set { _canCancelWorker = value; } } private void WorkerThreadStart(object? argument) { Debug.Assert(_asyncOperation != null, "_asyncOperation not initialized"); object? workerResult = null; Exception? error = null; bool cancelled = false; try { DoWorkEventArgs doWorkArgs = new DoWorkEventArgs(argument); OnDoWork(doWorkArgs); if (doWorkArgs.Cancel) { cancelled = true; } else { workerResult = doWorkArgs.Result; } } catch (Exception exception) { error = exception; } var e = new RunWorkerCompletedEventArgs(workerResult, error, cancelled); _asyncOperation.PostOperationCompleted(_operationCompleted, e); } protected override void Dispose(bool disposing) { } } }