110,536
社区成员
发帖
与我相关
我的任务
分享
public partial class Form1 : Form
{
private Thread _thread;
private bool _isDisposed;
public Form1()
{
InitializeComponent();
}
private delegate void ChangeNumber(int i, string time);
private void SetLabel(int i, string time)
{
if (this._isDisposed)
return;
this.BeginInvoke((Action)delegate
{
label1.Text = time;
progressBar1.Value = i;
});
}
private void button2_Click(object sender, EventArgs e)
{
_thread = new Thread(DoWork);
_thread.IsBackground = true;
_thread.Start();
}
private void DoWork()
{
{
int a = 1000;
int b = 0;
for (int i = 0; i < a; i++)
{
for (int j = 0; j < a; j++)
{
for (int k = 0; k < a; k++)
{
b++;
}
}
if (_isDisposed)
{
return;
}
SetLabel(i, "Button2: " + DateTime.Now);
}
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
_isDisposed = true;
}
也就是说,使用 BeginInvoke 而基本上不使用 Invoke,而且一般不去判断 InvokeRequired。另外并不是非常频繁地去交互显示,交互显示之前使用 _isDisposed 标志是因为此时没有必要去显示了。
当然这只是逻辑上的设计,大多数时候并不需要 _isDisposed 这类标记,有这类标记大都数时候都是因为底层系统有 bug 所以才需要判断。异步处理要使用异步的流程设计,从不阻塞,因此异步代码其实更简洁、也不会纠结出来那么多 bug(异步处理并不会改变你安排好的处理代码执行顺序) if (this._isDisposed)
return;
确实是仍然无法防止 Invoke 跟 this.Close 冲突。这个可能算是 Form 对象的特列吧。我们基本上从未用过 Invoke,都是使用 BeginInvoke,而且 BeginInvoke 可以正常运行,可见 Form 的 Close 原本是可以跟线程异步执行正常并发的(Form.Close 并不会真正 GC 释放 Form 对象,它只是做一些内部处理)。所以既然连异步的 BeginInvoke都可以正常执行,那么同步的 Invoke 语句可能是有 bug。 public partial class Form1 : Form
{
private Thread _thread;
private bool _isDisposed;
public Form1()
{
InitializeComponent();
}
private delegate void ChangeNumber(int i, string time);
private void SetLabel(int i, string time)
{
if (!this._isDisposed)
return;
if (this.InvokeRequired)
{
ChangeNumber cn = SetLabel;
this.Invoke(cn, i, time);
}
else
{
label1.Text = time;
progressBar1.Value = i;
}
}
private void button2_Click(object sender, EventArgs e)
{
_thread = new Thread(DoWork);
_thread.IsBackground = true;
_thread.Start();
}
private void DoWork()
{
{
int a = 1000;
int b = 0;
for (int i = 0; i < a; i++)
{
for (int j = 0; j < a; j++)
{
for (int k = 0; k < a; k++)
{
b++;
}
}
if (_isDisposed)
{
return;
}
SetLabel(i, "Button2: " + DateTime.Now);
}
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
_isDisposed = true;
}
private void SetLabel(int i, string time)
{
if (this.InvokeRequired)
{
ChangeNumber cn = SetLabel;
this.BeginInvoke(cn, i, time);
}
else
{
label1.Text = time;
progressBar1.Value = i;
}
}
this.Invoke(del_1);
和调用this.BeginInvoke(del_1);
这两句,前一句出错,这个一般来说我们都作为设计上的一种缺陷来看待。因为 .net 类库设计者完全有能力使用跟后者相同的方法来直接结束,完全不用抛出异常,并不会产生什么问题。所以就觉得这里.net 功能就差这一点点改进功夫了。if(_IsDesposed) return;
也不行