Я пытаюсь сделать приложение для Windows, и у меня есть функция, выполнение которой занимает несколько минут. У меня есть кнопка запуска, и я хотел бы добавить кнопку остановки, чтобы остановить обработку функции всякий раз, когда я хочу ее остановить.
Я пытаюсь использовать приведенный ниже код, но я не уверен, как прервать Thread1 внутри btnStop, поскольку 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 и Алексею за рассказ об отмене жетонов. Следуя примеру в ссылке, которой вы поделились, я смог написать код ниже. Кажется, это работает, но я хотел бы получить одобрение от вас, экспертов, нужно ли что-то изменить или все в порядке.
Единственное сомнение в отношении текущего кода заключается в том, что если нажата кнопка «Стоп», обработка останавливается, но если я снова нажимаю кнопку «Пуск», ничего не происходит, и мне нужно закрыть и снова открыть приложение, чтобы снова заработала кнопка запуска, это это нормально?
Другое сомнение в части внутри «Слушателя». В примере 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");
}
}
}
}