[英]How to cancel execution of a long-running async task in a C# Winforms app
我是一個經驗不足的C#程序員,在管理程序流程方面需要幫助。 它是一個WinFormApp,它要求多個用戶輸入,然后使用它們與設備建立串行通信以進行測量。 使用異步方法進行測量,大約需要20分鍾才能運行。 所以我在用
void main()
{
//Setup
}
private void button1_Click(object sender, EventArgs e)
{
await measurements();
//Plot results
}
private async Task measurements()
{
while(true){
//Make some measurements
await Task.Delay(120000);
//Make measurements, present data in the UI form.
//return if done
}
}
現在,我需要創建一個按鈕,使用戶可以取消測量,以更改某些輸入或參數,然后重新啟動測量。 因此,我添加了“取消”按鈕。
private void button7_Click(object sender, EventArgs e)
{
textBox64.Enabled = true;
button6.Enabled = true;
button5.Enabled = true;
textBox63.Enabled = true;
button3.Enabled = true;
trackBar1.Enabled = true;
timer.Enabled = true;
button7.Enabled = false;
clearData();
// measurement.Stop();
}
現在我不知道如何管理程序的流程。 我試圖在button1_Click()
創建一個try-catch
結構,並從button7_Click
引發異常,但是它無法傳遞到button1_Click()
。
然后,我嘗試在新線程上運行measurements()
。 但是該線程無法訪問我的主窗體上的70多個UI項目。
甚至我也不會像嘗試Goto那樣陷入低谷。
我需要的是關於如何在這種情況下進行編程的建議,以便對應用程序有一個良好的控制,而不會因為異常和Goto之類的風險而損害程序的流程。
如果要中途取消實際任務,則需要查看使用CancellationTokenSource並將取消令牌傳遞到異步方法中。
這是有關該文檔的Microsoft文檔 ,在底部有一個很好的例子, 這是另一個很好的博客 ,展示了進度條並允許取消。 第二篇文章有一個很好的概述:
取消由CancellationToken結構控制。 您可以在可取消異步方法的簽名中公開取消令牌,從而使它們可以在任務和調用方之間共享。 在最常見的情況下,取消遵循以下流程:
- 調用方創建一個CancellationTokenSource對象。
- 調用方調用可取消的異步API,並從CancellationTokenSource(CancellationTokenSource.Token)傳遞CancellationToken。
- 調用方使用CancellationTokenSource對象(CancellationTokenSource.Cancel())請求取消。
- 任務確認取消並自行取消,通常使用CancellationToken.ThrowIfCancellationRequested方法。
為了使您的應用對取消請求做出快速響應,您需要使用長期運行的方法定期檢查取消令牌,並在請求取消的情況下做出相應的響應。
這是一些粗糙的代碼,但是應該可以解決問題。
使用CancellationToken。 我已經使用了切換方法來測試是否要取消異步任務。
CancellationTokenSource cts;
private async button1_Click(object sender, EventArgs e)
{
toggleAsyncTask(false)
}
private void toggleAsyncTask(bool isCancelled)
{
if(cts==null)
var cts = new CancellationTokenSource();
if(!isCancelled)
{
await measurements(cts.Token);
}
else
{
cts.Cancel();
cts.Dispose();
cts = null;
}
}
private async Task measurementsOne(CancellationToken token)
{
try
{
while(true){
//Make some measurements
await Task.Delay(120000); // don't know if you need this.
//Make measurements, present data in the UI form.
//return if done
}
catch(OperationCancelledException)
{
// to do if you please.
}
}
private void button7_Click(object sender, EventArgs e)
{
// button stuff
toggleAsyncTask(true); // isCancelled is true.
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.