简体   繁体   English

在 .NET 中,事件将在哪个线程中处理?

[英]In .NET, what thread will Events be handled in?

I have attempted to implement a producer/consumer pattern in c#.我试图在 C# 中实现生产者/消费者模式。 I have a consumer thread that monitors a shared queue, and a producer thread that places items onto the shared queue.我有一个监视共享队列的消费者线程和一个将项目放置到共享队列的生产者线程。 The producer thread is subscribed to receive data...that is, it has an event handler, and just sits around and waits for an OnData event to fire (the data is being sent from a 3rd party api).生产者线程被订阅以接收数据……也就是说,它有一个事件处理程序,只是坐在那里等待 OnData 事件触发(数据是从 3rd 方 api 发送的)。 When it gets the data, it sticks it on the queue so the consumer can handle it.当它获取数据时,它会将其粘贴在队列中,以便消费者可以处理它。

When the OnData event does fire in the producer, I had expected it to be handled by my producer thread.当 OnData 事件在生产者中触发时,我原以为它会由我的生产者线程处理。 But that doesn't seem to be what is happening.但这似乎不是正在发生的事情。 The OnData event seems as if it's being handled on a new thread instead! OnData 事件似乎是在一个新线程上处理的! Is this how .net always works...events are handled on their own thread?这是 .net 总是如何工作的...事件是在他们自己的线程上处理的吗? Can I control what thread will handle events when they're raised?我可以控制什么线程在引发事件时处理事件吗? What if hundreds of events are raised near-simultaneously...would each have its own thread?如果数百个事件几乎同时引发怎么办……每个事件都有自己的线程吗?

After re-reading the question, I think I understand the problem now.重新阅读问题后,我想我现在了解问题了。 You've basically got something like this:你基本上得到了这样的东西:

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

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

And then you've got a consumer thread that pulls stuff off that queue.然后你有一个消费者线程从队列中取出东西。 The problem is that the OnData event is fired by your ExternalSource object - on whatever thread it happens to be running on.问题是 OnData 事件是由您的ExternalSource对象触发的 - 在它碰巧运行的任何线程上。

C# event s are basically just an easy-to-use collection of delegates and "firing" an event just causes the runtime to loop through all of the delegates and fire them one at a time. C# event基本上只是一个易于使用的委托集合,“触发”事件只会导致运行时循环遍历所有委托并一次触发一个。

So your OnData event handler is getting called on whatever thread the ExternalSource is running on.所以你的 OnData 事件处理程序会在ExternalSource运行的任何线程上被调用。

Unless you do the marshaling yourself, an event will execute on whatever thread is invoking it;除非您自己进行封送处理,否则事件将在调用它的任何线程上执行; there's nothing special about the way events are invoked, and your producer thread doesn't have an event handler, your producer thread simply said "hey, when you fire this event, call this function".调用事件的方式没有什么特别之处,并且您的生产者线程没有事件处理程序,您的生产者线程只是说“嘿,当您触发此事件时,请调用此函数”。 There's nothing in there that causes the event execution to occur on the attaching thread, nor on its own thread (unless you were to use BeginInvoke rather than invoking the event's delegate normally, but this will just execute it on the ThreadPool ).那里没有任何东西会导致事件执行发生在附加线程上,也不会发生在它自己的线程上(除非您要使用BeginInvoke而不是正常调用事件的委托,但这只会在ThreadPool上执行它)。

Raising an event with Invoke is the same as calling a method - it gets executed in the same thread you raised it.使用Invoke引发事件与Invoke方法相同 - 它在您引发它的同一线程中执行。

Raising an event with BeginInvoke uses ThreadPool .使用BeginInvoke引发事件使用ThreadPool Here are some minor details这里有一些小细节

you have to use autoresetevent handlers for this problem.....in autoresetevent when producer produses it set the signal then consumer reset its signal and consume.. after consuming consume set signal then only producer produced...你必须使用 autoresetevent 处理程序来解决这个问题......

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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM