我在 WPF 應用程式中使用了 MVVM 模型。我有一個命令系結到取消按鈕。我有一個啟動按鈕,可以啟動一些后臺作業人員。當我單擊取消按鈕時,我希望所有后臺作業人員停止/退出。當我單擊取消按鈕時,使用我當前的代碼,后臺作業人員不會停止并且“StartEngineeringOperation”完成。任何人都可以幫我解決我在這里做錯了什么嗎?
當前代碼:
對于 EngineeringViewModel.cs:
公共類 EngineeringViewModel{
public EngineeringViewModel()
{
StartEngineering= new DelegateCommand(o =>
{
worker = new BackgroundWorker
{
WorkerReportsProgress = true,
WorkerSupportsCancellation = true
};
worker.ProgressChanged = Worker_ProgressChanged;
worker.RunWorkerCompleted = worker_RunWorkerCompleted;
if (worker.IsBusy != true) worker.RunWorkerAsync();
worker.DoWork = (s, e) =>
{
StartEngineeringOperation();
if (worker.CancellationPending)
{
e.Cancel = true;
return;
}
};
},
k => true);
Cancel = new DelegateCommand(CancelEngineeringOperation);
}
private void StartEngineeringOperation()
{
startAlarmService();
startTrendQualityCheck();
}
private void CancelEngineeringOperation(object param)
{
worker.DoWork = (s, e) =>
{
if (worker.IsBusy)
{
worker.CancelAsync();
e.Cancel = true;
return;
}
};
}
}
我試過這個:但似乎不起作用:
private void StartEngineeringOperation()
{
startAlarmService();
if (worker.CancellationPending)
{
e.Cancel = true;
return;
}
startTrendQualityCheck();
}
uj5u.com熱心網友回復:
正如您可能從 te 評論中了解到的那樣,您需要輪詢BackgroundWorker您想要支持取消的操作的狀態。然后采取措施優雅地取消正在進行的操作。
該示例顯示了如何在按鈕單擊時取消后臺執行緒。第一個示例使用舊的BackgroundWorker,第二個示例使用現代且更干凈的 Task 庫。
后臺作業者
private BackgroundWorker Worker { get; set; }
private void StartWorker()
{
this.Worker = new BackgroundWorker
{
WorkerReportsProgress = true,
WorkerSupportsCancellation = true
};
this.Worker.DoWork = BackgroundWorker_DoWork;
}
private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
DoCancellableWork();
// Stop BackgroundWorker from executing
if (worker.CancellationPending)
{
e.Cancel = true;
}
}
private void DoCancellableWork()
{
// Check for cancellation before executing the cancellable operation and allocating resources etc..
if (this.Worker.CancellationPending)
{
return;
}
// Periodically/regularly check for the cancellation flag
for (int i = 0; i <= 10000000000; i )
{
if (this.Worker.CancellationPending)
{
// Cancel operation gracefully e.g., do some cleanup, free resources etc.
return;
}
// Do some work
}
}
// Alternatively use a command e.g., in a view model class
private void CancelBackgroundWorker_Click(object sender, EventArgs e)
{
if (this.Worker.WorkerSupportsCancellation)
{
this.Worker.CancelAsync();
}
}
任務庫
該示例使用Progress<T>向 UI 執行緒報告從后臺執行緒的進度。
private CancellationTokenSource CancellationTokenSource { get; set; }
private async Task StartWorker()
{
this.CancellationTokenSource = new CancellationTokenSource();
// Prepare callback to update UI from the background thread.
// The Progress<T> instance MUST be created on the UI thread
IProgress<int> progressReporter = new Progress<int>(progress => this.ProgressBar.Value = progress);
await Task.Run(
() => DoWork(progressReporter, this.CancellationTokenSource.Token),
this.CancellationTokenSource.Token);
this.CancellationTokenSource.Dispose();
}
private void DoWork(IProgress<int> progressReporter, CancellationToken cancellationToken)
{
DoCancellableWork(progressReporter, cancellationToken);
}
private void DoCancellableWork(IProgress<int> progressReporter, CancellationToken cancellationToken)
{
// Check for cancellation before executing the operation and allocating resources etc..
if (cancellationToken.IsCancellationRequested)
{
return;
}
// Periodically/regularly check for the cancellation flag
for (int i = 0; i <= 10000000000; i )
{
if (cancellationToken.IsCancellationRequested)
{
// Cancel operation gracefully e.g., do some cleanup, free resources etc.
return;
}
// Do some work
// Report progress
progressReporter.Report(20);
}
}
// Alternatively use a command e.g., in a view model class
private void CancelBackgroundThread_Click(object sender, EventArgs e)
{
this.CancellationtokenSource?.Cancel();
}
uj5u.com熱心網友回復:
由于 OP 將正在完成的任務描述為“檢查服務”,我認為完成的作業如下所示:
while(true){
// check service
// Post result back to UI thread
Thread.Sleep(...);
}
這不是撰寫此類支票的最佳方式。在大多數使用 Thread.Sleep 的情況下,計時器將是更好的選擇:
var myTimer = new System.Timers.Timer(...);
myTimer .Elapsed = OnTimedEvent;
myTimer .AutoReset = true;
myTimer .Enabled = true;
...
private void OnTimedEvent(Object source, ElapsedEventArgs e)
{
// check service
// Post result back to UI thread
}
這使得停止/啟動正在完成的任務的問題成為更改計時器的啟用標志的簡單問題。也可以使用計時器或同步背景關系直接在 UI 執行緒上運行事件,如果“檢查服務”只需要幾毫秒,這可能是最好的解決方案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/359043.html
上一篇:觸摸控制元件外時,PreviewMouseLeftButtonDown事件偶爾會觸發
下一篇:while回圈未結束但條件已滿足
