C#如何使同步方法等待事件触发?
Posted
技术标签:
【中文标题】C#如何使同步方法等待事件触发?【英文标题】:C# How to make synchronous method waiting for events to fire? 【发布时间】:2012-06-10 22:30:39 【问题描述】:我有自定义浏览器类,它能够根据浏览的页面状态触发很多事件。现在我需要使用我的浏览器在这个网页上执行一些操作,但是它们必须按顺序运行,每个操作都需要前一个操作的数据。 实现这一点的最简洁方法是创建一个同步方法等待浏览器完成其工作。我是这样设计的:
public incomplete class MyClass
// (...) lots of stuff comes here, it's a web browser :)
public bool MySyncMethod(object data)
bool success = false;
bool wait = true;
MyEventHandler = new EventHandler((o, e) =>
data = MyEventProvidedData; // belive me, it's threre when it fired
success = true; // let's assume it always succeed
wait = false; // now we can move on to the rest of our long chain
);
// (...) here I have some more event handlers which can end my method...
MyAsyncMethod(data); // so it started and will fire MyEventHandler soon
while (wait) System.Threading.Thread.Sleep(100);
return success;
但这里似乎有些不对劲。如果我使用线程,我只需放置 myThread.Join() 而不是我的 while 循环,它会等待我的线程完成。是否类似于 Thread.Join() 可以与控件触发的事件一起使用?有什么东西可以代替while循环吗?这是实现我的目标的更清洁的方式吗?上面的代码在实际应用中可以运行,但我认为它不是最优的。
我在这里不使用线程有一个很好的理由——线程和 ActiveX 控件之间的所有通信都必须是线程安全的,而要实现这一点并非易事。是的,我试过了:)这段代码调试起来很麻烦,所以我决定重写它。
【问题讨论】:
您看过 Monitor.Pulse 的示例代码吗?在 MSDN 上:msdn.microsoft.com/en-us/library/… 【参考方案1】:尝试使用 ManualResetEvent:
var wait = new ManualResetEvent(false);
var handler = new EventHandler((o, e) => wait.Set());
MyAsyncMethod(data, handler); // so it started and will fire handler soon
wait.WaitOne();
【讨论】:
这也适用于具有多种类型的 Action 事件,因此上面的 EventHandler 可以替换为 Action【参考方案2】:如果可以使用任务,您可以使用WaitAll Method
但是你说你不能使用线程。仍然 asyncmethod 必须启动某种线程,所以必须涉及一些线程? 如果问题是 asyncmethod 必须回发到原始线程才能使活动 x 控件工作,您可以使用 ASyncOperationManager (无耻自己的博客文章链接:http://blog.subrosoftware.nl/?p=42),或者 MSDN link 可以解决线程回调问题?
【讨论】:
是的,你是对的 - 我必须使用线程,但我可以将跨线程调用限制在必要的最小值。我不必直接访问ActiveX,但我需要访问基于ActiveX 的WebBrowser 组件。可以使用 Invoke 实现线程安全。因此,大多数使用浏览器的代码将在包含浏览器的表单类中完成 - 在其线程中。只有启动任务和接收数据才需要调用,所以非常简单。以上是关于C#如何使同步方法等待事件触发?的主要内容,如果未能解决你的问题,请参考以下文章