最近我遇到了一个专有的第三方库,并且有一种方法就是这样:
public Point ClickOnDrawMat(DrawMat drwmat)
{
Point pt;
//waiting user mouse click on DrawMat and assign to pt
return pt;
}
当我的代码从主线程调用此方法时,它将阻止此方法,直到用户单击,然后从ClickOnDrawMat
返回点。
public void button1_Click(object sender, EventArgs e)
{
Point userClickedPoint = ClickOnDrawMat(oDrwMat); //Wait until user clicked
//Do stuff with point we got
}
但是,它不会阻止主线程。我仍然可以在等待用户点击的同时按下其他按钮/ UI控件 我注意到在等待用户点击时,其中一个CPU内核使用率似乎很高(~75%)。
这是我在等待用户点击后点击另一个按钮后调用堆栈的示例:
myProgram.frmMain.button2_Click(xxx) Line 23
[External Code]
ThirdPartyLib.ClickOnDrawMat(xxx) Line 16
myProgram.frmMain.button1_Click(xxx) Line 14
我想知道如何做到这一点? 提前谢谢!
答案 0 :(得分:7)
我们无法确切地告诉你它是如何完成的,除非somone有一个库的副本,并且他们使用一个decomplier来查看代码正在做什么(如果你想自己做dotPeek是免费的,使用方便)。
但是,根据你如何描述它的行为,它可能会在函数内部重复调用Application.DoEvents()
,这会让其他消息在长时间运行的过程中被处理。
由于其高昂的CPU成本,这几乎是 从不 轮询操作的良好编码实践,正如您所注意到的,我建议不要在您自己的代码中执行此操作。
处理此问题的“正确”方法是使用Asynchronous Programming Patterns之一:在.NET 4.5中添加的async/await feature或NuGet package for 4.0(TAP),库引发自己的事件(EAP),或者在完成时使用函数使用回调函数(APM)。在函数本身内部,它应该在内部使用事件驱动系统,以便在等待事件发生而不是轮询时不使用CPU电源。