我需要在线程和事件引发方面具有高技能的人。
我有一个抽象类 A
和两个具体类 C1
、C2
(例如插件)。
因为我需要它们相互通信,比如“插件-应用程序”“插件-插件”通信,我在抽象类中有一个方法 ExecuteCommand
应该完成这个。此函数向应用程序引发一个 event
以处理某个命令并返回结果(例如,如果一个插件需要来自应用程序的数据,它会从基础调用 ExecuteCommand
并且等待在应用程序上处理的事件处理程序附带的结果。
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;
}
问题是:
如果 C1
和 C2
背后都有不同的线程,并从它们自己的线程内部同时调用 ExecuteCommand
那么我的设计肯定会被破坏,返回的结果将是意想不到的。
这个场景的最佳设计是什么?我正在考虑在 ExecuteCommand
内部使用异步调用,例如使用 AsyncOperation
...但这是正确的方法吗?
编辑: 我想我正在寻找:同步或异步方式更适合我的场景吗?或者,我应该让应用程序事件处理程序在插件的线程内处理还是在我的主线程中的某个地方同步?
如果能对您的建议做出一些很好的解释,我将不胜感激
谢谢。
最佳答案
在公共(public)资源或代码块上进行线程同步的通常简单方法是使用互斥量(或在本例中为临界区)。使用锁语句:
http://msdn.microsoft.com/en-us/library/c5kehkcz(VS.71).aspx
这篇文章说要锁定“this”指针,但这可能很危险,因为外部调用者也可以获得相同的锁,这可能会破坏您的程序。锁定私有(private)类变量。
这里是对您的示例代码的一些修改,以合并锁定/关键部分:
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 都会排队,并按顺序运行调度程序线程。
关于C# 多源、不同线程、一个事件处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3447189/