@artshelom

Как остановить поток?

Пытаюсь остановить поток:
wait.Stop = delegate ()
			{
				myThread.Abort();
			};
			myThread.Start();

В форме:
public Action Worker { get; }
		public Action Stop { get; set; }
		private Thread thread;
		public FormWait(Action worker)
		{
			InitializeComponent();
			if (worker == null)
				throw new ArgumentNullException();
			Worker = worker;
		}
		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);
			//thread = new Thread(new ThreadStart(delegate ()
			//{
			//	Worker();
			//}));
			//thread.Start();
			Task.Factory.StartNew(Worker).ContinueWith(t => { this.Close(); }, TaskScheduler.FromCurrentSynchronizationContext());
		}

		private void button1_Click(object sender, EventArgs e)
		{
			Console.WriteLine("Stop");
			Stop();
		}


Но почему то не срабатывает, как можно сделать остановку потока?
  • Вопрос задан
  • 700 просмотров
Пригласить эксперта
Ответы на вопрос 1
lexxpavlov
@lexxpavlov
Программист, преподаватель
Останавливать поток нужно не убиванием его, а остановкой, желательно - изнутри. А чтобы это можно было сделать нужно передать внутрь токен останова. Сам останов ничего не делает, но он используется внутри тела потока для отмены или аварийного завершения. Этот токен передастся в Worker, в котором нужно будет проверять наличие останова с помощью cancellationToken.IsCancellationRequested. Если в воркере используется цикл, то проверять можно в каждой итерации.

var formWait = new FormWait(cancellationToken => 
{
    foreach(var item in _items)
    {
        if (cancellationToken.IsCancellationRequested)
        {
            return;
        }
        item.DoWork();
    }
});


wait.Stop = delegate ()
      {
        var source = _tokenSource;
        if (source != null)
        {
            source.Cancel();
            source.Dispose();
            _tokenSource = null;
        }
      };
      myThread.Start();

В форме:
    public Action<CancellationToken> Worker { get; } // добавляем ссылку на токен останова
    public Action Stop { get; set; }
    private CancellationTokenSource _tokenSource;
    public FormWait(Action<CancellationToken> worker)
    {
      InitializeComponent();
      if (worker == null)
        throw new ArgumentNullException();
      Worker = worker;
    }
    protected override void OnLoad(EventArgs e)
    {
      base.OnLoad(e);
      _tokenSource?.Dispose();
      _tokenSource = new CancellationTokenSource();
      var cancellationToken =  = _tokenSource.Token;
      Task.Factory.StartNew(() => Worker(cancellationToken ))
          .ContinueWith(t => { this.Close(); }, TaskScheduler.FromCurrentSynchronizationContext());
    }

    private void button1_Click(object sender, EventArgs e)
    {
      Console.WriteLine("Stop");
      Stop();
    }


Возможно, хорошо сделать таск с возвращаемым результатом, например
public Func<CancellationToken, bool> Worker { get; }

Task.Factory.StartNew<bool>(() => Worker(cancellationToken))
.ContinueWith(t => { if (t.Result) this.Close(); }, TaskScheduler.FromCurrentSynchronizationContext());
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы