C#多个来源,不同的线程,一个事件处理程序 [英] C# multiple sources, different threads, one event handler

查看:182
本文介绍了C#多个来源,不同的线程,一个事件处理程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一个在线程和事件提升方面具有很强技能的人。



我有一个抽象类 A 两个具体的课程 C1 C2 (例如插件)。



由于我需要他们在彼此之间进行通信,如plugin-applicationplugin-plugin通信,我有一个方法 ExecuteCommand 在抽象类中应该实现这一点。该函数向应用程序引发一个事件,以便处理某个命令并返回结果(例如,如果一个插件需要来自应用程序的数据,它调用 ExecuteCommand ,并等待应用程序处理的事件处理程序附带的结果)。

  protected object ExecuteCommand(SvcCmdType cmdType,params object [] inputParams)
{
//这个代码已被简化
SvcCommandEventArgs eventArgs = new SvcCommandEventArgs(cmdType,inputParams);

//生成处理命令事件(需要填写结果)
OnProcessingAppCommand(this,eventArgs);

return eventArgs.OutputParamsList;
}

问题 是:



如果每个 C1 C2 后面有不同的线程,同时从他们自己的线程内部同时调用 ExecuteCommand 然后确定我的设计将被破坏,返回的结果将是意想不到的。



这种情况最好的设计是什么?我正在考虑使用 ExecuteCommand 中的异步调用,例如使用 AsyncOperation ...但是它是正确的方式吗? p>

编辑:
我想我在寻找:对于我的场景,是同步还是异步的方式?或者,我应该在插件的线程中处理应用程序事件处理程序或在主线程中的某处同步?



我真的很感激您的建议的一些很好的解释



谢谢。

解决方案

通常在一个线程同步的简单方法公共资源或代码块是使用互斥体(或者在这种情况下是关键部分)。使用锁定语句:



http://msdn.microsoft.com/en-us/library/c5kehkcz(VS.71).aspx



这篇文章说要锁定this指针,但这可能是危险的,因为外部调用者也可以获取相同的锁,这可能会破坏你的程序。对私有类变量进行锁定。



以下是您的示例代码的一些修改,以纳入锁定/重要部分:



pre $ class SomeClass:ISomeInterface
{
protected object ExecuteCommand(SvcCmdType cmdType,params object [] inputParams)
{
lock (executeCommandLock)
{
SvcCommandEventArgs eventArgs = new SvcCommandEventArgs(cmdType,inputParams);
OnProcessingAppCommand(this,eventArgs);
return eventArgs.OutputParamsList;
}
}

private Object executeCommandLock = new Object();
}

编辑:



(从评论中释义)。你提到你可能想要在单个线程上异步处理对ExecuteCommand的所有调用。您可以使用Dispatcher类来完成此操作:



http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.aspx



在一个线程上获取对调度程序的引用。传递给其他线程的引用。当这些线程想要调用ExecuteCommand时,它们使用dispatcher.BeginInvoke。由于它们使用BeginInvoke,所以对ExecuteCommand的所有调用都将异步运行,而不会阻塞该线程。然而,每个版本的ExecuteCommand都将被排队,并按顺序调度线程。


I need somebody with high skills in threading and event raising.

I have an abstract class A and two concrete classes C1, C2 (e.g plugins).

Since I need them to communicate between each other, like "plugin-application" "plugin-plugin" communication, I have a method ExecuteCommand in the abstract class which should accomplish this. This function raises an event to the application in order to process a certain command and return the result (e.g if one plugin needs data from the app it calls ExecuteCommand from the base and waits for the result which comes with the event handler processed on the application).

protected object ExecuteCommand(SvcCmdType cmdType, params object[] inputParams)
{
  // this code has been simplified
  SvcCommandEventArgs eventArgs = new SvcCommandEventArgs(cmdType, inputParams);

  // generate processing command event (it requires to fill in the result)
  OnProcessingAppCommand(this, eventArgs);

  return eventArgs.OutputParamsList; 
}

The problem is:

If each one of C1 and C2 have different threads behind and call simultaneously ExecuteCommand from inside their own threads then for sure my design will be broken and the result returned will be unexpected.

What is the best design for this scenario? I was thinking to use inside ExecuteCommand asynchronous calls like using AsyncOperation... but is it the right way?

edited: I guess I am looking for: is the synchronous or asynchronous way better for my scenario? Or, shall I have the app event handler processed inside a plugin's thread or synchronized somewhere in my main thread?

I would really appreciate some good explanations for your recommendations

Thank you.

解决方案

The usual simple method of doing thread synchronization on a common resource or code block is to use a mutex (or, in this case, a critical section). Use the lock statement:

http://msdn.microsoft.com/en-us/library/c5kehkcz(VS.71).aspx

This article says to do locking on the "this" pointer, but that can be dangerous, as outside callers could also acquire the same lock, which could break your program. Do your locking on a private class variable.

Here is some modification of your example code to incorporate locking/a critical section:

class SomeClass : ISomeInterface
{
  protected object ExecuteCommand(SvcCmdType cmdType, params object[] inputParams)
  {
    lock(executeCommandLock)
    {
      SvcCommandEventArgs eventArgs = new SvcCommandEventArgs(cmdType, inputParams);
      OnProcessingAppCommand(this, eventArgs);
      return eventArgs.OutputParamsList; 
    }
  }

  private Object executeCommandLock = new Object();
}

Edit:

(paraphrasing from comments). You mentioned that you might want to process all calls to ExecuteCommand on a single thread, asynchronously. You may be able to accomplish this with the Dispatcher class:

http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.aspx

Get a reference to the dispatcher on one thread. Pass that reference to the other threads. When those threads want to call ExecuteCommand, they use dispatcher.BeginInvoke. Since they use BeginInvoke, all calls to ExecuteCommand will then operate asynchronously, and not block on that thread. However, each version of ExecuteCommand will be queued up, and run sequentially dispatcher thread.

这篇关于C#多个来源,不同的线程,一个事件处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆