2014-09-05 88 views
2

我已查找解决方案,但什么也没找到。在一个永久线程中运行事件处理程序

在某些类我有事件

public class ClassWithEvent 
{ 
    public event Action<string> SomeEvent; 

    ... 
} 

与此事件在主线程有用户

public class SubscriberClass 
{ 
    public void SomeMethod(string value) 
    { 
     ... 
    } 
} 

ClassWithEvent objectWithEvent = new ClassWithEvent(); 

SubscriberClass subscriberObject = new SubscriberClass(); 

objectWithEvent.SomeEvent += subscriberObject.SomeMethod; 

某处这个事件可以被调用。

if(SomeEvent != null) 
    SomeEvent(someString); 

而当它发生它的处理程序必须在第二个线程中运行。但是每次都在同一个线程中,所以第二个线程必须是永久的,并且在第一次执行后不会被终止。

请帮我实施这个。

回答

6

创建一个共享队列:

private BlockingCollection<string> queue = new BlockingCollection<string>(); 

创建竭诚为您的线程:该线程

Thread thread = new Thread(HandleEvents); 
thread.Start(); 

过程事件:

private void HandleEvents() 
{ 
    foreach (string someValue in queue.GetConsumingEnumerable()) 
    { 
     //Do stuff 
    } 
} 

将物品放入队列时,该事件是提出:

objectWithEvent.SomeEvent += (x) => queue.Add(x); 

在关机完成队列:

queue.CompleteAdding(); 
+0

取而代之的是'while'循环的更简单的方法是'{的foreach(在queue.GetConsumingEnumerable()字符串someValue中)//完成东西}'。它的行为与你的版本相同,除了Take()在多用户环境中有竞争条件的机会,它可以在已经完成的集合上调用它。 'Take()'抛出一个异常,'GetConsumingEnumerable()'只是退出'foreach'循环。 – 2014-09-05 21:50:03

+0

@ScottChamberlain同意。 – Zer0 2014-09-05 21:55:00

-2

那么它是相当棘手,但它应该工作。

您将需要通过启动而(真)有创建永久线程,例如,和操作的列表,将这个循环内进行检查,这样的事:

ConcurrentBag<Action> actions = new ConcurrentBag<Action>(); 
new Thread(
delegate() 
{ 
    while (true) 
    { 
     Action a; 
     if (actions.TryTake(out a)) 
      a(); 
    } 
} 
).Start(); 

而且每次你想升到事件只是操作添加到列表:

actions.Add(new Action(() => { SomeEvent("abc"); })); 
+0

好吧,我亲爱的downvoters,我只是试图展示一种方式去,但这里是线程安全版本的代码添加到袋子。 – VladL 2014-09-05 22:06:01

+0

@VladL如果袋子是空的,这个代码将持续地在while循环中旋转CPU循环。如果行李不是空的,那么您将不会从行李箱中取出,因此会重复执行相同的“动作”。 – Zer0 2014-09-06 08:07:48

+0

@ Zer0 TryPeek与Stack的Pop()类似。如果有一个 – VladL 2014-09-06 08:44:07

相关问题