[英]Stop long running events
我有一個由另一個表單 Form1 打開的以下表單 Form3,當關閉 Form1 時,它會重新打開。
問題是當我關閉 Form3 時,DoSomething 在表單關閉后繼續運行。
我知道我可以將 DoSomething 變成一個線程並設置 IsBackground = true 但還有另一種方法可以在表單關閉時停止所有進程。
此代碼只是示例,用於說明。
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
private void DoSomething()
{
int i = 0;
while(true)
{
if (!this.IsDisposed)
{
Application.DoEvents();
i++;
Thread.Sleep(10);
label1.Text = i.ToString();
dataGridView1.Rows.Add();
}
}
}
private void button1_Click(object sender, EventArgs e)
{
DoSomething();
}
private void Form3_FormClosed(object sender, FormClosedEventArgs e)
{
this.Dispose();
Form1.Default.Show();
}
}
你永遠不會突破 while(true)。 您應該在 IsDisposed 為 true 時中斷循環,將 while 循環更改為 while(!IsDisposed),或者存儲使用確定何時中斷循環的類級別變量。
我可能會選擇后者,因為它給了你更多的控制權。
public partial class Form3 : Form
{
volatile bool clDoSomething;
public Form3()
{
InitializeComponent();
}
private void DoSomething()
{
int i = 0;
clDoSomething = true;
while(clDoSomething)
{
Application.DoEvents();
++i;
Thread.Sleep(10);
label1.Text = i.ToString();
dataGridView1.Rows.Add();
}
}
private void button1_Click(object sender, EventArgs e)
{
DoSomething();
}
private void Form3_FormClosed(object sender, FormClosedEventArgs e)
{
clDoSomething = false;
Form1.Default.Show();
}
}
你的基本方法有缺陷。
首先,應避免使用Application.DoEvents,除非您確定確實需要它並且正確使用它。 您在這里不需要它,並且您沒有正確使用它。
你真正需要的是一個Timer
。
private Timer timer = new Timer();
private int count = 0;
public Form3()
{
InitializeComponent();
timer.Tick += timer_Tick;
timer.Interval = 10;
//when the form is closed stop the timer.
FormClosed += (_, args) => timer.Stop();
}
private void button1_Click(object sender, EventArgs e)
{
count = 0;
timer.Start();
}
private void timer_Tick(object sender, EventArgs e)
{
count++;
label1.Text = count.ToString();
dataGridView1.Rows.Add();
}
創建Form
時,配置Timer
。 滴答事件與間隔一起設置。 滴答事件看起來類似於你的DoSomething
方法; 它將涉及每 10 秒從 UI 線程運行一些代碼,同時保持 UI 響應。 當表單關閉時,只需停止計時器,它將停止觸發這些事件。
另請注意,在此示例中,多次按下按鈕只會重置計時器和計數,它最終不會創建兩個循環,每個循環每 10 毫秒觸發一次。
根據需要覆蓋this.Dispose()
或this.Close()
並手動this.Close()
DoSomething() 。
感謝 cdhowie 的建議和所有其他人的投入。 將 DoEvents 修剪到最后並添加 IsDipsosed 解決了我的問題。
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
private void DoSomething()
{
int i = 0;
while ((true) && !this.IsDisposed)
{
i++;
Thread.Sleep(10);
label1.Text = i.ToString();
dataGridView1.Rows.Add();
Application.DoEvents();
}
}
private void button1_Click(object sender, EventArgs e)
{
DoSomething();
}
private void Form3_FormClosed(object sender, FormClosedEventArgs e)
{
Form1.Default.Show();
}
}
嘗試在 FormClosing 事件中添加此指令: System.Diagnostics.Process.GetCurrentProcess().Kill();
有點像這樣:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
System.Diagnostics.Process.GetCurrentProcess().Kill();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.