我正在动态实例化一个表单。在创建句柄之前,我无法与表单上的组件(例如TextBox)进行交互(否则,将抛出异常)。
目前我使用while循环阻止线程:
public void OutputDesktopFrame(MessagingService service, DesktopFrame desktopFrame)
{
IRemoteDesktopView view = GetView(service);
view.UpdateFrame(desktopFrame);
}
private IRemoteDesktopView GetView(MessagingService service)
{
T view;
bool viewExists = _views.TryGetValue(service, out view);
if (viewExists == false)
{
view = CreateAndShowView(service);
}
return view;
}
private T CreateAndShowView(MessagingService service)
{
T remoteDesktopView = new T();
_views.Add(service, remoteDesktopView);
Thread pumpThread = new Thread(() => remoteDesktopView.ShowDialog());
pumpThread.Start();
while (remoteDesktopView.IsHandleCreated == false)
{
//Do not return until the handle has been created!
}
return remoteDesktopView;
}
我不喜欢这种机制。我正在寻找一个优雅的解决方案。
请考虑我正在编码接口。我想过使用ManualResetEvent之类的东西,但是必须在实现接口的每个Form中实现和处理ManualResetEvent听起来不吸引我。如果你不同意我的意见。那很好。我只是怀疑我目前的解决方案并不是最优雅的。
答案 0 :(得分:6)
您可以将代码添加到HandleCreated
事件处理程序中,如下所示:
private void Form1_HandleCreated(object sender, EventArgs e){
//your code
}
事件未在“属性”窗口中列出,您必须使用代码注册事件处理程序:
HandleCreated += Form1_HandleCreated;
答案 1 :(得分:2)
你必须等待以某种方式创建句柄。
因此,您最终会在代码中的某处找到类似while (form.IsHandleCreated == false) { ... }
的内容。
唯一的问题是在哪里放。
如果您在上面的示例中执行此操作,则需要在每次创建表单时对while
循环进行编码如果您选择使用表单引发的事件提及的替代方法,则需要实现它以每种形式出现(并创建一个事件处理程序并将其挂钩)。
我不知道CreateAndShowForm()
是否是一种框架方法,或者您可以自行更改的内容。如果你可以改变它,那就是我要等待的地方。这样你只需要编码一次。
避免代码重复的另一种方法是在表单中处理它,在您自己的抽象表单基类中实现它,并从该类派生实际表单。在我看来,对于这个问题来说,这是完全矫枉过正的 - 太多的工作只能获得很少的收益。
如果您无法更改CreateAndShowForm()
,我建议您使用上面的示例 - 是的,它绝对不优雅,但它完成了工作,源代码很容易理解,并且它没有不需要额外的事件处理工作。