假设我有一个暴露的界面:
interface IMyService
{
MyResult MyOperation();
}
此操作是同步的并返回一个值。
我实现的界面必须执行以下操作:
这是由于我正在使用的第三方COM对象。
此代码类似于以下
public MyResult MyOperation()
{
_myCOMObject.AsyncOperation();
//Here I need to wait for both events to fire before returning
}
private void MyEvent1()
{
//My Event 1 is fired in this handler
}
private void MyEvent2()
{
//My Event 2 is fired in this handler
}
我的两个事件可以按任意顺序发生,它是随机的。
我可以使用哪种正确的线程机制来同步它?在我不得不开始等待第二个事件之前,我正在使用ManualResetEvent,并且还没有看到一种简单的方法将它用于这两个事件。这两个事件设置变量,允许我为MyOperation()创建返回值。
关于良好实施的任何想法?我无法控制第三方对象的实现方式。
答案 0 :(得分:4)
两个ManualResetEvent
应该为你做的伎俩。在调用_myCOMObject.AsyncOperation()
之前,只需将它们初始化为false即可。像这样:
private ManualResetEvent event1;
private ManualResetEvent event2;
public MyResult MyOperation()
{
event1 = new ManualResetEvent(false);
event2 = new ManualResetEvent(false);
_myCOMObject.AsyncOperation();
WaitHandle.WaitAll(new WaitHandle[] { event1, event2 });
}
private void MyEvent1()
{
event1.Set();
}
private void MyEvent2()
{
event2.Set();
}
修改
感谢您的评论。我已将等待通话更改为使用WaitAll
答案 1 :(得分:2)
我的实现示例如下:
namespace ConsoleApplication1
{
class Program
{
private static WaitHandle[] waitHandles;
private static event EventHandler Evt1;
private static event EventHandler Evt2;
static void Main(string[] args)
{
waitHandles = new WaitHandle[]{
new ManualResetEvent(false),
new ManualResetEvent(false)
};
Evt1 += new EventHandler(Program_Evt1);
Evt2 += new EventHandler(Program_Evt2);
OnEvt1();
OnEvt2();
WaitHandle.WaitAll(waitHandles);
Console.WriteLine("Finished");
Console.ReadLine();
}
static void Program_Evt2(object sender, EventArgs e)
{
Thread.Sleep(2000);
((ManualResetEvent)waitHandles[0]).Set();
}
static void Program_Evt1(object sender, EventArgs e)
{
((ManualResetEvent)waitHandles[1]).Set();
}
static void OnEvt1()
{
if (Evt1 != null)
Evt1(null, EventArgs.Empty);
}
static void OnEvt2()
{
if (Evt2 != null)
Evt2(null, EventArgs.Empty);
}
}
}
为了本示例和WaitAll功能
,我让它休眠干杯,
安德鲁
P.S。另一个例子是使用AsyncCallback,非常快速和肮脏的例子,但给你更多的钥匙打开门:-)。希望这会有所帮助!!
namespace ConsoleApplication1
{
class Program
{
private static WaitHandle[] waitHandles;
private static event EventHandler Evt1;
private static event EventHandler Evt2;
static void Main(string[] args)
{
waitHandles = new WaitHandle[]{
new ManualResetEvent(false),
new ManualResetEvent(false)
};
var callabck1 = new AsyncCallback(OnEvt1);
var callabck2 = new AsyncCallback(OnEvt2);
callabck1.Invoke(new ManualResetResult(null, (ManualResetEvent)waitHandles[0]));
callabck2.Invoke(new ManualResetResult(null, (ManualResetEvent)waitHandles[1]));
WaitHandle.WaitAll(waitHandles);
Console.WriteLine("Finished");
Console.ReadLine();
}
static void OnEvt1(IAsyncResult result)
{
Console.WriteLine("Setting1");
var handle = result.AsyncWaitHandle;
((ManualResetEvent)handle).Set();
}
static void OnEvt2(IAsyncResult result)
{
Thread.Sleep(2000);
Console.WriteLine("Setting2");
var handle = result.AsyncWaitHandle;
((ManualResetEvent)handle).Set();
}
}
public class ManualResetResult : IAsyncResult
{
private object _state;
private ManualResetEvent _handle;
public ManualResetResult(object state, ManualResetEvent handle)
{
_state = state;
_handle = handle;
}
#region IAsyncResult Members
public object AsyncState
{
get { return _state; }
}
public WaitHandle AsyncWaitHandle
{
get { return _handle; }
}
public bool CompletedSynchronously
{
get { throw new NotImplementedException(); }
}
public bool IsCompleted
{
get { throw new NotImplementedException(); }
}
#endregion
}
}
答案 2 :(得分:0)
我不确定我理解你的问题,但是如果我做对了,AutoResetEvent.WaitAll似乎可以解决你的问题。它允许您设置多个处理程序,只有在设置了所有处理程序后才会释放它。