ManualResetEvent не работает; Нить

У меня есть клиент, который создает поток.

Этот поток имеет WaitOne(), поэтому, пока он застрял там, мой клиент не умирает. Но когда я хочу закрыть свой клиент, мне нужно выполнить Set() для этого события ручного сброса.

Я объявляю событие ручного сброса в основном классе:

public ManualResetEvent mreIn = new ManualResetEvent(false);

Это моя функция Connect, которая создает поток с функцией запуска:

    public void Connect()
    {
        objClientThread = new Thread(start) { IsBackground = true };
        objClientThread.Start();
    }

    /// <summary>
    /// Starts the client program.
    /// </summary>
    private void start()
    {
            //We Open the proxy to let connections happen
            objProxy.Open();
            if (performHandshake())
            {
                IsConnected = true;
                DelayedShutdownBool = false;
                //While connected, the thread keeps the client alive
                mreIn.WaitOne();
                if (OnShutdownInitiated != null)
                {
                    OnShutdownInitiated(this, new EventArgs());
                }
                System.Threading.Thread.Sleep(500);
                objProxy.Close();
                objConfiguration = null;
                IsConnected = false;
                mreOut.Set();
            }
        }

И у меня есть обратный вызов, который выполняет Set():

    Boolean IServiceCallbackContract.Shutdown()
    {
        mreIn.Set();
        return true;
    }

Это работает так: все модули инициализируются и блокируются на WaitOne(). Когда я завершаю работу модуля, обратный вызов выполняет Set(), но WaitOne() не разблокируется, и поток не продолжается. Что мне не хватает?


person AAlferez    schedule 16.08.2013    source источник
comment
Первая проверка: выполняется ли обратный вызов на том же экземпляре?   -  person Henk Holterman    schedule 16.08.2013
comment
Да, обратный вызов запускает тот же экземпляр. Клиент — это .exe, выполняемый с помощью executeAssembly. Этот .exe имеет экземпляр клиентского класса. Когда начинается exe, вызывается функция Connect(), создающая поток   -  person AAlferez    schedule 16.08.2013
comment
Но ваш objProxy выглядит как неправильно названный Host.   -  person Henk Holterman    schedule 16.08.2013
comment
objProxy настроен на доступ к конечной точке и имеет конфигурацию, позволяющую netNamedPipes найти сервер. Не имеет к этому никакого отношения   -  person AAlferez    schedule 16.08.2013
comment
Я провел дополнительное тестирование, похоже, что все, что делается в обратном вызове, не выполняется, как и другой объект. Как я могу убедиться, что обратный вызов выполняется для того же объекта?   -  person AAlferez    schedule 16.08.2013
comment
возможный дубликат Ожидание в потоке, создающем экземпляр который создает поток   -  person Henk Holterman    schedule 17.08.2013
comment
@HenkHolterman публикует ответ, чтобы я мог его принять, проблема заключалась в неправильном контексте обратного вызова, поэтому он не отвечал на тот же экземпляр. Спасибо :)   -  person AAlferez    schedule 19.08.2013
comment
Вы можете опубликовать ответ самостоятельно, у вас есть более подробная информация. Все, что может помочь будущему гуглеру, который попадет сюда.   -  person Henk Holterman    schedule 19.08.2013


Ответы (3)


Проблема заключалась в том, что при создании клиента службы мне нужно было передать контекст экземпляра обратных вызовов, и я выполнял new, поэтому я не помещал контекст экземпляра current, а обратный вызов выполнялся для другого экземпляра, поэтому каждый изменение значений или события, которое я делал, не отражалось в текущем экземпляре. Спасибо @HenkHolterman за помощь :)

person AAlferez    schedule 19.08.2013

Похоже, вы правильно используете ManualResetEvent. Но ваша тема фоновая. Если все другие нефоновые потоки завершатся, то ваш поток будет прерван в случайном месте, и код после mreIn.WaitOne() может не выполняться.

Если это так, то проблема может быть решена, если ваш therad не будет работать в фоновом режиме.

person alex    schedule 16.08.2013
comment
Этот фоновый поток управляет другим потоком с помощью обработчика событий. И другая ветка точно не умерла. Уверен на 100%. - person AAlferez; 16.08.2013

обратите внимание на этот пример:

class ThreadManager : IThreadManager
{
    private System.Threading.ManualResetEvent _Mre;
    private static CancellationTokenSource _CancellationToken;
    private int _ThreadCount;

    public ThreadManager(int threadCount)
    {
        _Mre = new System.Threading.ManualResetEvent(true);
        _CancellationToken = new CancellationTokenSource();
        _ThreadCount = threadCount;
    }

    public void DoWork(Action action)
    {
        _Mre.WaitOne();
        Task.Factory.StartNew(action, _CancellationToken.Token);
    }

    public void Stop()
    {
        _CancellationToken.Cancel();
    }

    public void Resume()
    {
        _Mre.Set();
    }

    public void Waite()
    {
        _Mre.Reset();
    }
}
person mohammad almasi    schedule 05.03.2019