Подтвердить что ты не робот

В .NET, в какой поток будут обрабатываться события?

Я попытался реализовать шаблон производителя/потребителя в С#. У меня есть потребительский поток, который контролирует общую очередь и поток производителя, который помещает элементы в общую очередь. Нить производителя подписана на получение данных... то есть у него есть обработчик событий и он просто сидит и ждет, когда событие OnData будет запущено (данные отправляются с стороннего api). Когда он получает данные, он помещает его в очередь, чтобы потребитель мог справиться с этим.

Когда событие OnData срабатывает у продюсера, я ожидал, что он будет обработан моим потоком производителя. Но, похоже, это не то, что происходит. Событие OnData выглядит так, как будто оно обрабатывается вместо нового потока! Это как .net всегда работает... события обрабатываются в собственном потоке? Могу ли я контролировать, какой поток будет обрабатывать события, когда они будут подняты? Что, если сотни событий поднимаются почти одновременно... каждый будет иметь свой собственный поток?

4b9b3361

Ответ 1

После повторного чтения вопроса, я думаю, теперь я понимаю проблему. У вас в основном есть что-то вроде этого:

class Producer
{
    public Producer(ExternalSource src)
    {
        src.OnData += externalSource_OnData;
    }

    private void externalSource_OnData(object sender, ExternalSourceDataEventArgs e)
    {
        // put e.Data onto the queue
    }
}

И тогда у вас есть потребительский поток, который вытаскивает вещи из этой очереди. Проблема в том, что событие OnData запускается вашим объектом ExternalSource - в любом потоке, на котором он выполняется.

С# event - это просто простой в использовании набор делегатов и "запуск" события просто заставляет среду выполнения циклически проходить через всех делегатов и запускать их по одному за раз.

Итак, ваш обработчик события OnData получает вызов в любом потоке, на котором работает ExternalSource.

Ответ 2

Если вы не выполните маршалинг самостоятельно, событие будет выполняться на любом потоке, вызывающем его; нет ничего особенного в том, как вызываются события, а в потоке производителя нет обработчика событий, ваш поток производителя просто сказал: "Эй, когда вы запускаете это событие, вызывайте эту функцию". Там ничего нет, что приводит к тому, что выполнение события происходит на присоединяющем потоке или в его собственном потоке (если вы не использовали BeginInvoke, а не вызывали делегат события в обычном режиме, но это просто выполнит его на ThreadPool).

Ответ 3

Поднятие события с Invoke совпадает с вызовом метода - он запускается в том же потоке, который вы его создали.

При создании события с BeginInvoke используется ThreadPool. Вот несколько мелких деталей

Ответ 4

вам нужно использовать autoresetevent обработчики для этой проблемы..... в autoresetevent, когда продюсер продюсирует, он устанавливает сигнал, затем потребитель reset его сигнал и потребляет. после потребления потребляемого набора сигнала тогда производится только производитель...

AutoResetEvent pro = new AutoResetEvent(false);
AutoResetEvent con = new AutoResetEvent(true);

public void produser()
{

    while(true)
    {
        con.WaitOne();

        pro.Set();
    }
}

public void consumer()
{
    while (true)
    {
    pro.WaitOne();
       .................****

    con.Set();
    }
}

private void button1_Click(object sender, EventArgs e)
{
    Thread th1 = new Thread(produser);
    th1.Start();
    Thread th2 = new Thread(consumer);
    th2.Start();
}