2

我正在动态实例化一个表单。在创建句柄之前,我无法与表单上的组件(例如 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 或类似的东西,但必须在实现接口的每个表单中实现和处理 ManualResetEvent 对我来说听起来并不吸引人。如果你不同意我的话。没关系。我只是怀疑我目前的解决方案不是最优雅的。

4

2 回答 2

7

HandleCreated您可以像这样向事件处理程序添加代码:

private void Form1_HandleCreated(object sender, EventArgs e){
   //your code
}

该事件未在“属性”窗口中列出,您必须使用代码注册事件处理程序:

HandleCreated += Form1_HandleCreated;
于 2013-07-02T10:55:48.347 回答
2

您必须等待以某种方式创建句柄。所以你最终会while (form.IsHandleCreated == false) { ... }在你的代码中得到类似的东西。唯一的问题是放在哪里。

如果您像上面的示例中那样执行此操作,则while每次创建表单时都需要对循环进行编码如果您选择提到的替代方案,使用表单引发的事件,则需要在每个表单中实现它(并创建一个事件处理程序并将其连接起来)。

我不知道CreateAndShowForm()是框架方法,还是您可以自己更改的东西。如果你能改变它,那就是我会等待的地方。这样你只需要编码一次。

避免代码重复的另一种方法是在表单中处理它,在您自己的抽象表单基类中实现它,并从该类派生实际表单。在我看来,对于这个问题来说,这完全是矫枉过正——工作量太大而收效甚微。

如果您无法更改CreateAndShowForm(),我建议您使用上面的示例 - 是的,它绝对不优雅,但它可以完成工作,源代码易于理解,并且不需要额外的事件工作处理。

于 2013-07-02T10:57:28.910 回答