none
Как правильно сделать синхронизацию RRS feed

  • Вопрос

  • Добрый день!

    Подскажите как правильно сделать:

    1. Есть WinForms приложение, по кнопке старт создается поток, который в процессе своей работы обновляет GUI элементы.

    2. По другой кнопке требуется остановить работу первого потока, дождаться когда он остановится и запустить его снова с другими параметрами.

    Вопрос, как правильно остановить поток и дождаться момента когда можно запустить второй?

    Следующий код вешает приложение, понятно почему, но не ясно как сделать правильно. Можно сделать через Thread.Interupt но может быть есть более красивый способ?

     

    private ManualResetEvent manualResetEvent= new ManualResetEvent(false);

    private void start_Click(object sender, EventArgs e)
            {
                manualResetEvent.Reset();

                workThread = new Thread(() => DoWork());
                workThread.Start();
            }

            private void stop_Click(object sender, EventArgs e)
            {
                Debug.WriteLine(workThread.ManagedThreadId);

                manualResetEvent.Set();
                workThread.Join();            
            }

    private void DoWork()
    {
        int i = 0;

        while (true)
        {
            i++;

            MethodInvoker methodInvoker = delegate()
            {
                for (long ii = 0; ii < 10000; ii++)
                {
                    tbResult.Text = i.ToString();
                }

            };

            this.Invoke(methodInvoker);

            if (manualResetEvent.WaitOne(100))
            {
                break;
            }
        }
    }

    Александр

    4 июля 2014 г. 13:11

Ответы

  • Часто встречаю такие конструкции в коде: new Thread(() => DoWork()); Лямбда здесь совершенно ни к чему.

    Про отмену читайте здесь: Отмена в управляемых потоках.

    Применительно к вашему коду:

    Thread workThread;
    CancellationTokenSource cts;
    
    private void startButton_Click(object sender, EventArgs e)
    {
        cts = new CancellationTokenSource();
        workThread = new Thread(DoWork);
        workThread.Start();
    }
    private void restartButton_Click(object sender, EventArgs e)
    {
        cts.Cancel(); // делаем запрос на отмену
    
        // Ждём, пока поток завершится.
        // Это может вызвать "подвисание" GUI, если итерации цикла долгие.
        workThread.Join();
    
        cts.Dispose(); // освобождаем ресурс
    
        // Запускаем заново тот же метод.
        // Здесь можно изменить какие-то параметры.
        cts = new CancellationTokenSource();
        workThread = new Thread(DoWork);
        workThread.Start();
    }
    private void DoWork()
    {
        int i = 0;
        while (!cts.IsCancellationRequested)
        {
            i++;
            MethodInvoker methodInvoker = delegate()
            {
                //for (long ii = 0; ii < 10000; ii++)
                {
                    tbResult.Text = i.ToString();
                }
            };
            this.Invoke(methodInvoker);
            Thread.Sleep(100);
        }
    }

    4 июля 2014 г. 19:36