我正在尝试做一个 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,感谢您的帮助,当我仅将线程声明为全局变量时,我得到“SampleStartStop.exe 中发生了“System.NullReferenceException”类型的未处理异常”。
嗨阿列克谢,感谢您的更正。感谢 zerkms 和 Alexei 分享有关取消令牌的信息。按照您共享的链接中的示例,我能够编写下面的代码。它似乎有效,但如果它需要一些改变或者它是否可以,我希望你们专家的认可。
关于当前代码的唯一疑问是,如果按下停止按钮,它会停止处理正常,但是如果我再次单击开始按钮,什么也不会发生,我需要关闭并再次打开应用程序才能再次开始按钮,是这正常吗?
另一个疑问是在“听者”里面的部分。在 MSDN 示例中,他们输入“// Perform cleanup if necessary.”,那么,他们在谈论什么样的清理?
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");
}
}
}
更新: 感谢 Alexei 的更正,我已经根据您的建议修改了代码,这次效果很好。代码如下。我只有一个问题,因为在我的真实代码中,函数需要一个字符串参数才能工作,我不知道如何在“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");
}
}
}
}