首页 / C# / c# – 在关闭表单之前等待任务完成
c# – 在关闭表单之前等待任务完成
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – 在关闭表单之前等待任务完成,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3049字,纯文字阅读大概需要5分钟。
内容图文
![c# – 在关闭表单之前等待任务完成](/upload/InfoBanner/zyjiaocheng/818/025a7c39797a40e780e78c3c02f95b2d.jpg)
如何使FormClosing事件处理程序(在UI线程上执行)等待在同一表单上调用的任务完成?
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
cancelUpdater.Cancel(); // CancellationTokenSource
if (!updater.IsCompleted)
{
this.Hide();
updater.Wait(); // deadlock if updater task is inside invoke
}
}
private void Form1_Shown(object sender, EventArgs e)
{
cancelUpdater = new CancellationTokenSource();
updater = new Task(() => { Updater(cancelUpdater.Token); });
updater.Start();
}
void Updater(CancellationToken cancellationToken)
{
while(!cancellationToken.IsCancellationRequested)
{
this.Invoke(new Action(() => {
...
}));
//Thread.Sleep(1000);
}
}
解决方法:
处理此问题的正确方法是取消Close事件,然后在任务完成时关闭表单.这可能看起来像这样:
private async void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
cancelUpdater.Cancel(); // CancellationTokenSource
if (!updater.IsCompleted)
{
this.Hide();
e.Cancel = true;
await updater;
this.Close();
}
}
现在,在你的评论中,你写道:
the Close() method called by a form B will return immediately and the changes that form B will make will crash the updater
由于您没有发布任何与“表单B”相关的代码,因此不清楚它为何或如何与当前的Form1代码有关.很可能有一种很好的方法来修复这个“表单B”,以便它与Form1类和正在关闭的对象更好地协作.但是,如果没有看到明确显示这种相互作用的实际good, minimal, complete code example,那么就不可能建议它如何起作用.
坦率地说,阻止任何UI事件处理程序是一个非常糟糕的主意.允许UI线程继续运行是非常重要的,否则就是邀请死锁.你当然在这里找到了一个死锁的例子.但是,即使你解决了这个特定的例子,你也可以避免所有其他的死锁事件.
阻止UI线程只是要求死锁,以及其他问题.
也就是说,如果你不能用“表单B”来解决这个问题,并且真的觉得你必须阻塞该线程,你可以让跨线程调用使用BeginInvoke()而不是Invoke()(这使得调用本身是异步的,这样你的“更新线程”将能够继续运行然后终止).当然,如果你这样做,你将不得不更改代码来处理这样一个事实:当你的调用代码运行时,表单已经关闭.这可能是也可能不是一个简单的修复.
所有这一切,虽然我不能确定缺少一个好的代码示例,我强烈怀疑你真的不应该首先有这个更新程序任务,而应该使用System.Windows.Forms.Timer类.该类专门用于处理必须在UI线程中执行的周期性事件.
例如:
首先,将Timer对象拖放到设计器中的表单上.默认情况下,名称为timer1.然后将Interval属性设置为您在任务中使用的1000毫秒延迟.另外,更改Updater()方法,使其声明为timer1_Tick(object sender,EventArgs e),并将其用作计时器Tick事件的事件处理程序.
然后,更改您的代码,使其看起来像这样:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
timer1.Stop();
}
private void Form1_Shown(object sender, EventArgs e)
{
timer1.Start();
}
void timer1_Tick(object sender, EventArgs e)
{
// All that will be left here is whatever you were executing in the
// anonymous method you invoked. All that other stuff goes away.
...
}
由于System.Windows.Forms.Timer类在UI线程上引发其Tick事件,因此没有线程争用条件.如果你在FormClosing事件中停止计时器,那就是它.计时器停止了.当然,由于计时器的Tick事件是在UI线程上引发的,因此不需要使用Invoke()来执行代码.
恕我直言,以上是根据问题中的信息可以提供的最佳答案.如果您认为上述内容无效或适用,请编辑您的问题以提供所有相关详细信息,包括一个好的代码示例.
内容总结
以上是互联网集市为您收集整理的c# – 在关闭表单之前等待任务完成全部内容,希望文章能够帮你解决c# – 在关闭表单之前等待任务完成所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。