我正在考虑一种简单的方法来完成任务完成其工作。我提出了以下解决方案(将其粘贴到WinForms应用程序,只需一个按钮进行测试):
public partial class Form1 : Form
{
private Thread thread;
public void DoFinishWork() {
// [4]
// UI thread - waiting for thread to finalize its work
thread.Join();
// Checking, if it really finished its work
MessageBox.Show("Thread state: " + thread.IsAlive.ToString());
}
public void DoWork() {
// [2]
// Working hard
Thread.Sleep(1000);
}
public void FinishWork() {
// [3]
// Asynchronously notifying form in main thread, that work was done
Delegate del = new Action(DoFinishWork);
this.BeginInvoke(del);
// Finalizing work - this should be switched
// at some point to main thread
Thread.Sleep(1000);
}
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
// [1]
// Schedule the task
ThreadStart start = new ThreadStart(DoWork);
// Schedule notification about finishing work
start += FinishWork;
thread = new Thread(start);
thread.Start();
}
}
这是一个简单的取消场景,因此只有一个线程,它将与UI线程并行运行。
是否有更简单(或更加线程安全)的方式为Thread
实现此类通知?
请考虑两个事实:
Abort
它(因为我无法控制线程中的内容 - 第三方代码)BackgroundWorker
,因为它只提供正常终止的方式。答案 0 :(得分:0)
是否有更简单(或更多线程安全)的方式为Thread实现此类通知?
是的,使用TPL并让框架担心管理线程
Task.StartNew(() => {
// do some stuff
}).ContinueWith((task) => {
// do some stuff after I have finished doing some other stuff
});
或者,由于您正在使用WinForms,请使用BackgroundWorker并处理RunWorkerCompleted事件。
我把 kill 的概念误认为取消 - 没有可靠的方法在.NET中实际杀死一个线程,即使documentation建议使用Abort
或多或少都是一场赌博,绝对不会让线索真正被杀死。此外,它会留下线程,因此,应用程序处于不可预测的状态,因此如果您愿意冒这个风险,那么这取决于您。
另一种选择是简单地让线程播出,但只是忽略结果,这取决于任务的大小,这可能不是什么大不了的事。
答案 1 :(得分:0)
虽然您需要Abort
来终止线程,但您仍然可以使用TPL。您可以在任务中启动该线程,并等待CancellationToken
。在线程完成之前取消任务时,您可以在线程上调用Abort
。
它看起来像那样:
// In your class:
ManualResetEvent threadFinished = new ManualResetEvent(false);
// In your calling function (button1_Click):
Task.Run( () => {
ThreadStart threadStart = new StreadStart(DoWork);
threadStart += () => { threadFinished.Set(); }
Thread thread = new Thread(threadStart);
threadFinished.Reset();
thread.Start();
WaitHandle waitCancel = cancellationToken.WaitHandle;
int waited = WaitHandle.WaitAny( new WaitHandle[]{ waitCancel, threadFinished } );
if (waited == 0 && cancellationToken.IsCancellationRequested)
thread.Abort();
else
thread.Join()
});