我正在尝试做一个Windows应用程序,我有一个功能,需要几分钟才能完成任务。我有一个开始按钮 我想添加一个停止按钮,以便在我想要停止它时停止处理该功能。
我正在尝试使用下面的代码,但我不确定如何在btnStop中中止Thread1,因为Thread1被标记为“不存在 在目前的背景下“。
请你建议我/指点我如何做到这一点的好方法。提前谢谢。
namespace SampleStartStop
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
Thread Thread1 = new Thread(SlowFunction);
Thread1.Start();
}
private void btnStop_Click(object sender, EventArgs e)
{
Thread1.Abort();
MessageBox.Show("Processing canceled");
}
public void SlowFunction()
{
var end = DateTime.Now + TimeSpan.FromSeconds(10);
while (DateTime.Now < end)
{ }
MessageBox.Show("Process finished");
}
}
}
更新 嗨KCdod,感谢您的帮助,当我只将线程声明为全局变量时,我得到“类型'System.NullReferenceException'的未处理异常' 发生在SampleStartStop.exe“。
嗨阿列克谢,谢谢你的纠正。感谢zerkms和Alexei分享有关取消令牌的信息。按照您分享的链接示例 我能够编写下面的代码。它似乎有效,但如果它需要一些改变或者它是好的话,我想要专家的认可。
关于当前代码的唯一疑问是,如果按下停止按钮,则停止处理正常,但如果我再次单击开始按钮, 没有任何反应,我需要关闭并再次打开应用程序才能再次启动按钮,这是正常的吗?
另一个疑问是在“听众”中。在MSDN示例中,他们将“//必要时执行清理。”,那么,什么样的清理 他们在说什么?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// Create the token source.
CancellationTokenSource cts = new CancellationTokenSource();
private void btnStart_Click(object sender, EventArgs e)
{
// Pass the token to the cancelable operation.
ThreadPool.QueueUserWorkItem(new WaitCallback(SlowFunction), cts.Token);
}
private void btnStop_Click(object sender, EventArgs e)
{
// Request cancellation.
cts.Cancel();
// Cancellation should have happened, so call Dispose.
cts.Dispose();
MessageBox.Show("Processing canceled");
}
public void SlowFunction(object obj)
{
CancellationToken token = (CancellationToken)obj;
var end = DateTime.Now + TimeSpan.FromSeconds(10);
while (DateTime.Now < end)
{
// Thread 2: The listener
if (token.IsCancellationRequested)
{
// Perform cleanup if necessary.
//...
// Terminate the operation.
break;
}
}
if (!token.IsCancellationRequested)
{
MessageBox.Show("Processing finished");
}
}
}
更新 感谢阿列克谢的纠正,我已经修改了你的建议代码,这次工作很好。代码如下。我只有一个问题,因为在我的实际代码中,函数需要一个字符串参数才能工作,我不知道如何在“WaitCallback(SlowFunction)”部分内调用它以及如何在代码中定义函数,因为这里定义如下“public void SlowFunction(object obj){...}”,在我的实际函数中就像这样“public void SlowFunction(string str)”。我认为我需要在一个新问题中提出这个问题。
namespace SampleStartStop
{
public partial class Form1 : Form
{
// Create the token source.
CancellationTokenSource cts = new CancellationTokenSource();
public Form1()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
if (cts != null)
{
cts.Cancel();
}
// Pass the token to the cancelable operation.
cts = new CancellationTokenSource();
ThreadPool.QueueUserWorkItem(new WaitCallback(SlowFunction), cts.Token);
}
private void btnStop_Click(object sender, EventArgs e)
{
if (cts != null)
{
cts.Cancel();
cts = null;
MessageBox.Show("Processing canceled");
}
}
public void SlowFunction(object obj)
{
CancellationToken token = (CancellationToken)obj;
var end = DateTime.Now + TimeSpan.FromSeconds(5);
while (DateTime.Now < end)
{
if (token.IsCancellationRequested)
{
break;
}
}
if (!token.IsCancellationRequested)
{
MessageBox.Show("Processing finished");
}
}
}
}
答案 0 :(得分:4)
没有好方法来终止不合作的线程。确实Thread.Abort
会这样做,但是可能会留下非处置对象和放弃的同步原语,因此可能会破坏你的程序稳定。
修复您的直接问题 - 将Thread1
移动为类级别成员而不是本地变量。您需要检查它是否已设置/清除:
public partial class Form1 : Form {
...
Thread thread1 = null;
private void btnStart_Click(object sender, EventArgs e)
{
if (thread1 != null)
{
thread1.Abort();
}
thread1 = new Thread(SlowFunction);
Thread1.Start();
}
private void btnStop_Click(object sender, EventArgs e)
{
if (thread1 != null)
{
thread1.Abort();
thread1 = null;
MessageBox.Show("Processing canceled");
}
}
如果你可以使“慢功能”在终止中合作会更好 - 即通过定期检查某些值。检查Cancellation tokens .Net的方式。
答案 1 :(得分:1)
您可以将线程Thread Thread1;
声明为全局变量。在您当前的代码中,Thread1
范围限制为btnStart_Click()
事件函数。
namespace SampleStartStop
{
public partial class Form1 : Form
{
Thread Thread1=null;
public Form1()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
Thread1 = new Thread(SlowFunction);
Thread1.Start();
}
private void btnStop_Click(object sender, EventArgs e)
{
Thread1.Abort();
MessageBox.Show("Processing canceled");
}
public void SlowFunction()
{
var end = DateTime.Now + TimeSpan.FromSeconds(10);
while (DateTime.Now < end)
{ }
MessageBox.Show("Process finished");
}
}
}
Additional - 线程中止不好但你可以使用它。