Нежелательное завершение потока, созданного в обратном вызове таймера - PullRequest
1 голос
/ 06 ноября 2010

Вот что я хочу сделать:

  1. Есть таймер с некоторым интервалом
  2. В коде обратного вызова таймера, если выполняется какое-либо условие, должен выполняться другой поток

Я поместил свой код в класс, для которого создается основная форма, и код выполняется при вызове метода («StartSync ()», пример кода).

Проблема в том, что код выполняется в течение нескольких секунд, но затем завершается. Я полагаю, я делаю что-то глупое, но я действительно не вижу, что это такое. Благодарю за любую помощь в этом.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;

namespace WindowsFormsApplication1
{
    class Syncer
    {
        static bool SYNC_IN_PROGRESS;

        public void StartSync()
        {
            SYNC_IN_PROGRESS = false;
            Timer timer = new Timer(timerCallback, null, 0, 1000);
        }

        public void timerCallback(Object stateInfo)
        {
            Debug.WriteLine("Sync?");

            if (!SYNC_IN_PROGRESS)
            {
                SYNC_IN_PROGRESS = true;

                Thread thSync = new Thread(new ThreadStart(sync));
                thSync.Start();
            }
        }

        void sync()
        {
            Debug.WriteLine("Syncing...");
            SYNC_IN_PROGRESS = false;
        }
    }
}

Ответы [ 3 ]

1 голос
/ 06 ноября 2010

При догадке , Timer содержится только в переменной метода; для меня это звучит , как если бы Timer собирал и завершал сборку мусора, следовательно, прекращал работу. Я подозреваю, что вы должны удерживать эту ссылку в поле , чтобы предотвратить сбор.

Как отступление - я сомневаюсь, что это причина здесь, но при работе с потоками вы должны быть религиозно осведомлены о доступе к общему состоянию из нескольких потоков; например:

  • с использованием Monitor (он же lock)
  • правильное использование volatile
  • Interlocked когда подходит

Ваш текущий доступ к static bool будет , вероятно, работать нормально, но ...

0 голосов
/ 06 ноября 2010

Попробуйте этот более чистый подход

    static volatile bool SYNC_IN_PROGRESS; 
    static thread syncPoll; 

    public void StartSync() 
    { 
        SYNC_IN_PROGRESS = false; 
        syncPoll = new Thread(sync);
        syncPoll.Start();
    } 

    void sync() 
    { 
        while (true)
        {
             Debug.WriteLine("Sync?");
             if (SYNC_IN_PROGRESS) Debug.WriteLine("Syncing..."); 
             Thread.Sleep(1000);
        }
    } 

Он делает то же самое, что вы пытаетесь сделать с текущим кодом :), но не использует таймер

0 голосов
/ 06 ноября 2010

Так вот, что я сделал, и, кажется, работает отлично

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        private void button1_Click(object sender, EventArgs e)
        {
            StartSync();
        }

        static bool SYNC_IN_PROGRESS;

        public void StartSync()
        {
            SYNC_IN_PROGRESS = false;
            System.Threading.Timer timer = new System.Threading.Timer(timerCallback, SYNC_IN_PROGRESS, 0, 1000); 


        }

        public void timerCallback(Object stateInfo)
        {
            Debug.WriteLine("Sync?");

            if (!(bool)stateInfo)
            {
                SYNC_IN_PROGRESS = true;

                Thread thSync = new Thread(new ThreadStart(sync));
                thSync.Start();
            }
        }

        void sync()
        {
            Debug.WriteLine("Syncing...");
            SYNC_IN_PROGRESS = false;
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...