C#线程处理机制
问题描述:
比方说,我有一个暴露的接口,例如:C#线程处理机制
interface IMyService
{
MyResult MyOperation();
}
此操作是同步的,并返回一个值。
我实现接口具有执行以下操作:
- 呼叫异步方法
- 等待事件#1
- 等待事件#2
这是由于一个与我合作的第三方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()创建返回值。
关于良好实施的任何想法?我无法控制第三方对象的实现方式。
答
两个ManualResetEvent
s应该为你做的伎俩。在致电_myCOMObject.AsyncOperation()
之前,只需将它们初始化为假。就像这样:
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
答
我不知道我理解你的问题,但AutoResetEvent.WaitAll似乎解决了你的问题,如果我说得对。它允许您设置多个处理程序,并且只有在全部设置后才会释放。
答
我实现的例子如下:
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功能
干杯的目的,
安德鲁
PS另一个例子是使用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
}
}
这是有道理的。我的困惑是在多个ManualResetEvents的Reset()上调用哪一个,并且我还必须将整个调用锁定到MyOperation(),以便两个线程不能同时调用该函数。 – jonathanpeppers 2009-08-11 16:29:25
尽管这是一个非常好的解决方案,但我会使用WaitAll(如下所示)而不是两个WaitOne阻塞调用,WaitAll为系统提供了有关阻塞的更多上下文,并有可能为更好的调度提供机会。 – meandmycode 2009-08-11 16:31:32
感谢您的反馈。我已经更新了我的答案。 – 2009-08-11 17:56:20