Как дождаться завершения выполнения потока в С#?

У меня есть функция, которая вызывается в быстрой последовательности, которая имеет открытое соединение с базой данных. Моя проблема в том, что перед закрытием одного соединения с базой данных вызывается другой экземпляр функции, и я могу получить тупиковую ситуацию в базе данных.

Я пытался:

private static WaitHandle[] waitHandles = new WaitHandle[]
    {
        new AutoResetEvent(false)
    };

protected override void Broadcast(Data data, string updatedBy)
    {
        Action newAction = new Action(() =>
        {
        DataManagerFactory.PerformWithDataManager( 
            dataManager =>
            {
                // Update status and broadcast the changes
                data.UpdateModifiedColumns(dataManager, updatedBy);

                BroadcastManager.Instance().PerformBroadcast(
                    data,
                    BroadcastAction.Update,
                    Feature.None);
            },
            e => m_log.Error(ServerLog.ConfigIdlingRequestHandler_UpdateFailed() + e.Message));
            }
        );

        Thread workerThread = new Thread(new ThreadStart(newAction));
        ThreadPool.QueueUserWorkItem(workerThread.Start, waitHandles[0]);
        WaitHandle.WaitAll(waitHandles);
    }

но я получаю ошибку потока, и программа зависает. Я считаю, что это как-то связано с функцией запуска потока, не имеющей параметров.

Спасибо за любую помощь


person jordan    schedule 05.11.2012    source источник
comment
Второй объект в QueueUserWorkItem — это параметр. См. MSDN.   -  person Mike Park    schedule 06.11.2012
comment
Обычно вы не ставите в очередь метод Start нового потока в потоке ThreadPool. Это противоречит цели. Просто поставьте в очередь newAction. Вероятно, вам следует заблокировать какой-либо метод на вашей стороне (PerformBroadcast?), Это может привести к взаимоблокировке на стороне сервера.   -  person Mike Zboray    schedule 06.11.2012
comment
ThreadPool.QueueUserWorkItem(newAction, null); не работает. ThreadPool.QueueUserWorkItem(newAction, waitHandles[0]); не работает.   -  person jordan    schedule 06.11.2012


Ответы (1)


Вот как это делается. Создайте класс, который выполняет эту работу:

public class MyAsyncClass
{

    public delegate void NotifyComplete(string message);
    public event NotifyComplete NotifyCompleteEvent;

    //Starts async thread...
    public void Start()
    {
        System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(DoSomeJob));
        t.Start();
    }

    void DoSomeJob()
    {
        //just wait 5 sec for nothing special...
        System.Threading.Thread.Sleep(5000);
        if (NotifyCompleteEvent != null)
        {
            NotifyCompleteEvent("My job is completed!");
        }
    }
}

Теперь это код из другого класса, который вызывает первый:

 MyAsyncClass myClass = null;


    private void button2_Click(object sender, EventArgs e)
    {
        myClass = new MyAsyncClass();
        myClass.NotifyCompleteEvent += new MyAsyncClass.NotifyComplete(myClass_NotifyCompleteEvent);
        //here I start the job inside working class...
        myClass.Start();
    }

    //here my class is notified from working class when job is completed...
    delegate void myClassDelegate(string message);
    void myClass_NotifyCompleteEvent(string message)
    {
        if (this.InvokeRequired)
        {
            Delegate d = new myClassDelegate(myClass_NotifyCompleteEvent);
            this.Invoke(d, new object[] { message });
        }
        else
        {
            MessageBox.Show(message);
        }
    }

Дайте мне знать, если мне нужно объяснить некоторые детали.

Альтернативой этому является BackgroudWorker:

person Gregor Primar    schedule 05.11.2012
comment
Я просто жду окончания потока. я не хочу иметь собственный класс и не хочу использовать метод ожидания Action Fired. Есть какие-нибудь советы по простому ожиданию потока? у меня нет никаких действий, которые мне нужно выполнить после, мне просто нужно остановить выполнение родительского потока до тех пор, пока дочерний поток не будет выполнен, чтобы ни один дочерний поток не мог выполнить указанный код. блокировка блока кода не работает с общедоступной статической переменной только для чтения - person jordan; 06.11.2012
comment
Ближе всего к этому фоновый рабочий. Но вам придется написать несколько строк. Для получения дополнительных сведений перейдите по этой ссылке: msdn.microsoft. com/en-us/library/cc221403(v=vs.95).aspx - person Gregor Primar; 06.11.2012
comment
это также не сработает, так как в моем действии мне нужны пользовательские данные, недоступные в аргументах события - person jordan; 06.11.2012
comment
Насколько я понимаю вашу ситуацию, у вас не должно возникнуть проблем с использованием любого из этих решений. Если ожидание должно быть выполнено в пользовательском интерфейсе, просто отключите требуемую часть в форме. Если ожидание должно выполняться внутри кода, поместите закрытый параметр внутри вашего класса. Что-то вроде bool WorkingInProgress. При запуске задания установите WorkingInProgress=true. Удерживайте (используя while) любые другие процессы, пока NotifyCompleteEvent не доставит событие. Затем установите WorkingInProgress=false и продолжите со следующего потока в очереди. - person Gregor Primar; 06.11.2012