using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace ClassLibrary
{
public class MyClass
{
public static string LongOperation()
{
Thread.Sleep(new TimeSpan(0,0,30));
return "HelloWorld";
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ClassLibrary;
namespace BackgroungWorker__HelloWorld
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
return;
}
MyClass.LongOperation();
e.Result = "[Result]";
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
try
{
if (e.Cancelled)
{
MessageBox.Show("The task has been cancelled");
}
else if (e.Error != null)
{
MessageBox.Show("Error. Details: " + (e.Error as Exception).ToString());
}
else
{
MessageBox.Show("The task has been completed. Results: " + e.Result!=null?e.Result.ToString():" null");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnStart_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void btnClose_Click(object sender, EventArgs e)
{
if (backgroundWorker1.IsBusy)
{
backgroundWorker1.CancelAsync();
}
else
{
this.Close();
}
}
}
}
我在执行以下代码后发现:
private void btnClose_Click(object sender, EventArgs e)
{
if (backgroundWorker1.IsBusy)
{
backgroundWorker1.CancelAsync();
}
else
{
this.Close();//"this" means the Form object
}
}
backgroundWorker1的线程不会立即被杀死。这需要一些时间。
这是构建我的应用程序逻辑时的一个问题。
在这方面,有人可以帮助我吗?
答案 0 :(得分:4)
解决方案是更改BackgroundThread
的{{1}}事件处理程序以提高响应速度:它需要将其工作分解为更小的块并且频繁地轮询工作者DoWork()
以满足您的应用程序的需求。
修改:根据您添加的代码,您将无法使用CancellationPending
执行您想要的操作。
如果你不能修改BackgroudWorker
(并且它没有提供任何钩子让你打断它)但你想让用户在该操作完成之前取消,你可以通过创建自己的{{{ 1}}(作为后台线程,如果你放弃它,它将不会保持你的应用程序打开)。从理论上讲,您也可以使用MyClass.LongOperation
来执行此操作,但对于长时间运行的进程使用Thread
是个坏主意(有关详细信息,请参阅The Managed Thread Pool)。
最后,您可以考虑将长时间运行的操作移出带外 - 将消息写入队列,调用服务或使用其他技术将其移交给另一个进程。
答案 1 :(得分:1)
这取决于DoWork()
方法检查CancellationPending属性的频率。
这是取消请求,你不是要杀死线程。请参阅CancelAsync
上的msdn页面没有真正的方法强制终止BackgroundWorker,而是使用线程。
答案 2 :(得分:1)
由workerthreads代码检查CancellationPending属性。 将始终执行在这些检查之间执行的代码,从而导致延迟。
在你的评论中,你会发现一个很好的问题。
解决这个问题的一种方法是为多线程构建一个特定的子类,将不可避免的令人讨厌的位置留在逻辑之外。
主类应该为LongOperation提供一个调用其他方法的模板方法,然后线程子类可以覆盖longoperation中调用的方法,并且在让mainclass方法执行实际工作之前执行CancellationPending属性的检查。 / p>
这样你就可以比在长期操作结束时更加随意。
以非功能方式进行多线程处理将始终影响您的代码,在您需要锁定时保持不变; - )
答案 3 :(得分:0)
你能说明问题是什么吗?当然最好让后台工作线程优雅地完成(就像设计一样)。
您知道可以通过执行backgroundWorker1来定期检查取消。CancellationPending?