C#事件冒泡
我在实现以下目标方面遇到了一些困难: Form1有两个按钮“验证”和“取消”,还有一个BackgroundWorker。 Class1的处理方法很繁重 单击“验证”调用DoWork,其中繁重的工作是Class1的方法。我已经设法“倾听”了我工作中的进度变化事件,这些事件是由Class1方法引起的 现在,我正试图在单击cancel按钮时取消繁重的任务(在方法内部)C#事件冒泡,c#,winforms,events,backgroundworker,C#,Winforms,Events,Backgroundworker,我在实现以下目标方面遇到了一些困难: Form1有两个按钮“验证”和“取消”,还有一个BackgroundWorker。 Class1的处理方法很繁重 单击“验证”调用DoWork,其中繁重的工作是Class1的方法。我已经设法“倾听”了我工作中的进度变化事件,这些事件是由Class1方法引起的 现在,我正试图在单击cancel按钮时取消繁重的任务(在方法内部) private void buttonCancelValidation_Click(object sender, EventArgs
private void buttonCancelValidation_Click(object sender, EventArgs e)
{
backgroundWorker.CancelAsync();
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
Class1 obj = new Class1();
obj.ProgressChanged += (s, pe) => backgroundWorker.ReportProgress(pe.ProgressPercentage);
//---> Here a i'm trying to "tell" class1 that if the "Cancel" button was clicked then I want to abort ASAP the HeavyMethod operation.
obj.HeavyMethod();
//followed by the cancel of BackgroundWorker DoWork
if (backgroundWorker.CancellationPending
{
e.Cancel = true;
}
}
谢谢你的帮助 您的HeavyMethod()
代码必须能够访问一些变量,比如布尔变量,该变量应该指示是否需要立即返回。在HeavyMethod()
code中检查该变量值的频率将改变用户单击取消按钮和操作实际停止之间的延迟
bool cancelValidationRequest = false;
private void buttonCancelValidation_Click(object sender, EventArgs e)
{
cancelValidationRequest = true; // this will cause HeavyMethod return asap
backgroundWorker.CancelAsync(); // this makes requet to thread to stop, but it still in HeavyMethod...
}
和内部HeavyMethod()
像这样的,只是想给你一个想法
编辑
正如Wizetux指出的,您必须注意一个事实,即bolean值(在这个特定的例子中)是由不同的线程操作的
希望这能有所帮助。在不知道HeavyMethod是如何工作的情况下,唯一的方法是让线程等待HeavyMethod完成,或者提供一种从obj类中中断HeavyMethod的方法 您可以让Class1接受对backgroundWorker对象的引用,这样HeavyMethod就可以检查CancellationPending标志的值并打断该方法。只有当您的HeavyMethod有一个循环或一组较小的任务,您可以在任务之间检查此标志,以便尽早中断或从方法返回时,这才有效 你可以这样做
public class Class1
{
private BackgroundWorker _backgroundWorker = null;
public Class1(BackgroundWorkerThread worker)
{
_backgroundWorker = worker;
// rest of constructor
}
public void HeavyWorker()
{
// Heavy work
// Have we been cancelled.
if (_backgroundWorker != null && _backgroundWorker.CancellationPending)
{
// perform clean up and return
}
// Perform more heavy work.
}
}
private void backgroundWorker_DoWork(...)
{
Class1 obj = new Class1(backgroundWorker);
obj.HeavyMethod();
}
正如他所说的,您需要定期检查终止请求:由于您将从两个不同的线程设置并获取bool的值,因此您必须担心此任务的线程安全性,以免最终陷入竞争状态。我相信backgroundWorker对象在内部就可以做到这一点。@Tigran lol太简单了。。。呵呵。Obj在DoWork中实例化,因此在ButtonCancelValidation中不知道。将cancelValidationRequest设置为Class1中的静态属性可以吗?做了一个快速测试,一切正常。@Libas:我建议使用成员变量。看看这个:@Tigran要做到这一点,obj应该是Form1中的一个字段,不要太喜欢这个。谢谢你指出这个问题!我想我会去第二个Wizetuxsolution@Charles如何从FORM1到另一个单击了cancel的类对象方法进行判断。我只是在一个循环中用HeavyMethod读取一个文件,以便在该循环中中止它。如果是您的选择,您会选择第一个解决方案还是第二个?我想我在某个地方读到,将BGW传递给另一个类对象不是一个好主意。我不记得读过任何关于将BGW传递给另一个类对象的问题的文章,只要该对象仅在backgroundWorker执行期间存在。因为一旦线程完成了工作,就应该处理引用worker的对象。当您开始获取对过时后台工作人员的引用时,就会出现此问题。我会把上面看到的检查放在循环中,如果你被取消了,别忘了关闭文件。我会努力找到它,以确保我没有弄乱概念。所以,这是完美的,将使用这个解决方案,已经在另一个项目中使用,但实际上我有点不确定这种方法!谢谢
public class Class1
{
private BackgroundWorker _backgroundWorker = null;
public Class1(BackgroundWorkerThread worker)
{
_backgroundWorker = worker;
// rest of constructor
}
public void HeavyWorker()
{
// Heavy work
// Have we been cancelled.
if (_backgroundWorker != null && _backgroundWorker.CancellationPending)
{
// perform clean up and return
}
// Perform more heavy work.
}
}
private void backgroundWorker_DoWork(...)
{
Class1 obj = new Class1(backgroundWorker);
obj.HeavyMethod();
}