Поделиться через


Пошаговое руководство. Поддержка COM-взаимодействия путем отображения форм Windows Forms в совместно используемом потоке

Проблемы COM-взаимодействия можно устранить путем отображения формы в цикле обработки сообщений .NET Framework, который создается с помощью метода Application.Run.

Чтобы исправить работу формы Windows Forms из клиентского приложения COM, необходимо запустить его в цикле обработки сообщений Windows Forms. Для этого воспользуйтесь одним из перечисленных ниже подходов.

В следующем примере демонстрируется способ отображения форм Windows Forms в новом потоке с помощью общего цикла обработки сообщений.

Чтобы скопировать весь текст кода из этой темы, см. раздел Практическое руководство. Поддержка COM-взаимодействия путем отображения Windows Forms в общем потоке.

Процедура

Этот подход аналогичен процедуре, описанной в разделе Пошаговое руководство. Поддержка COM-взаимодействия путем отображения каждой формы Windows Forms в отдельном потоке. Однако вместо отображения каждой формы в своем собственном потоке с помощью собственного цикла обработки сообщений создается общий цикл обработки сообщений, который будет выполняться только в одном новом потоке в компоненте .NET Framework.

Этот подход более точно представляет поведение стандартного приложения Windows Forms. Он также упрощает совместное использование ресурсов между несколькими формами, так как все формы выполняются в одном и том же потоке. Решение из раздела Пошаговое руководство. Поддержка COM-взаимодействия путем отображения каждой формы Windows Forms в отдельном потоке создает новый поток для каждой формы. Для этого решения требуется дополнительный код синхронизации потоков для совместного использования ресурсов различными формами.

Поскольку отображение форм в общем потоке больше напоминает поведение приложения Windows Forms, будет показано, что с помощью .NET Framework Windows Forms клиентское приложение закрывается при остановке цикла обработки сообщений .NET Framework. Такое поведение наблюдается, когда пользователь закрывает форму, которая обозначается как главная форма для класса ApplicationContext. Класс ApplicationContext используется для запуска цикла обработки сообщений.

В следующих примерах кода главная форма класса ApplicationContext присваивается первой форме, которая открывается клиентским приложением. Таким образом, когда пользователь закрывает этот экземпляр формы, происходит выход из цикла обработки сообщений .NET Framework и все формы Windows Forms закрываются.

Создание общего цикла обработки сообщений для всех форм в новом потоке

  1. Создайте новый проект библиотеки классов и назовите его COMWinform.

  2. Удалите файл Class1.vb по умолчанию.

  3. В меню Проект выберите команду Добавить класс.

  4. Выберите шаблон COM-класс.

  5. В поле Имя введите COMForm.vb и нажмите кнопку Добавить.

  6. Вставьте следующие операторы в верхней части файла COMForm над определением класса.

    Imports System.Windows.Forms
    Imports System.Runtime.InteropServices
    
  7. В COMForm вставьте следующий код под определением конструктора.

    Private WithEvents frmManager As FormManager
    
    Public Sub ShowForm1()
        ' Call the StartForm method by using a new instance
        ' of the Form1 class.
        StartForm(New Form1)
    End Sub
    
    Private Sub StartForm(ByVal frm As Form)
    
        ' This procedure is used to show all forms
        ' that the client application requests. When the first form
        ' is displayed, this code will create a new message
        ' loop that runs on a new thread. The new form will
        ' be treated as the main form.
    
        ' Later forms will be shown on the same message loop.
        If IsNothing(frmManager) Then
            frmManager = New FormManager(frm)
        Else
            frmManager.ShowForm(frm)
        End If
    End Sub
    
    Private Sub frmManager_MessageLoopExit() Handles frmManager.MessageLoopExit
        'Release the reference to the frmManager object.
        frmManager = Nothing
    End Sub
    
  8. В меню Проект щелкните Добавить класс и выберите шаблон Класс.

  9. В поле Имя введите FormManager.vb и нажмите кнопку Добавить.

  10. Замените код в файле FormManager следующим кодом:

    Imports System.Runtime.InteropServices
    Imports System.Threading
    Imports System.Windows.Forms
    
    <ComVisible(False)> _
    Friend Class FormManager
        ' This class is used so that you can generically pass any
        ' form that you want to the delegate.
    
        Private WithEvents appContext As ApplicationContext
        Private Delegate Sub FormShowDelegate(ByVal form As Form)
        Event MessageLoopExit()
    
        Public Sub New(ByVal MainForm As Form)
            Dim t As Thread
            If IsNothing(appContext) Then
                appContext = New ApplicationContext(MainForm)
                t = New Thread(AddressOf StartMessageLoop)
                t.IsBackground = True
                t.SetApartmentState(ApartmentState.STA)
                t.Start()
            End If
        End Sub
    
        Private Sub StartMessageLoop()
            ' Call the Application.Run method to run the form on its own message loop.
            Application.Run(appContext)
        End Sub
    
        Public Sub ShowForm(ByVal form As Form)
    
            Dim formShow As FormShowDelegate
    
            ' Start the main form first. Otherwise, focus will stay on the 
            ' calling form.
            appContext.MainForm.Activate()
    
            ' Create a new instance of the FormShowDelegate method, and
            ' then invoke the delegate off the MainForm object.
            formShow = New FormShowDelegate(AddressOf ShowFormOnMainForm_MessageLoop)
            appContext.MainForm.Invoke(formShow, New Object() {form})
        End Sub
    
        Private Sub ShowFormOnMainForm_MessageLoop(ByVal form As Form)
            form.Show()
        End Sub
    
        Private Sub ac_ThreadExit(ByVal sender As Object, ByVal e As System.EventArgs) Handles appContext.ThreadExit
            appContext.MainForm.Dispose()
            appContext.MainForm = Nothing
            appContext.Dispose()
            appContext = Nothing
            RaiseEvent MessageLoopExit()
        End Sub
    End Class
    
  11. В меню Проект выберите Добавить форму Windows, затем щелкните Добавить.

  12. Добавьте к форме элементы управления TextBox и Button.

  13. Дважды щелкните Button1, чтобы добавить обработчик события Click.

  14. В обработчик события Click добавьте следующий код.

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        MessageBox.Show("Clicked button")
    End Sub
    
  15. Выполните сборку решения.

    На этом шаге проект также регистрируется для COM-взаимодействия на данном компьютере.

Чтобы создать исполняемый файл, демонстрирующий COM-взаимодействие

  1. Запустите Microsoft Visual Basic 6.0

  2. Создайте новый проект EXE.

  3. В меню Проект щелкните Ссылки.

  4. Добавьте ссылку на библиотеку типов COMWinform, которая была создана при построении решения Visual Basic 2005.

    -либо-

    Если библиотека отсутствует в списке, нажмите кнопку Обзор, чтобы вручную найти файл библиотеки (с расширением TLB).

  5. Добавьте в форму кнопку.

  6. В меню Вид выберите Код и добавьте следующий код в модуль формы.

Option Explicit

Private Sub Command1_Click()
    Dim frm As COMWinform.COMForm
    Set frm = New COMWinform.COMForm
    frm.ShowForm1
End Sub
  1. Чтобы скомпилировать проект, в меню Файл выберите команду Создать EXE.

  2. Запустите скомпилированный исполняемый файл Visual Basic 6.0.

  3. Для отображения формы Windows Forms из созданной ранее библиотеки классов нажмите кнопку.

  4. Установите фокус на один из элементов управления TextBox на форме Windows Forms и нажмите клавишу TAB для переключения элементов управления.

    Обратите внимание, что клавиша TAB перемещает фокус с одного элемента управления на другой. Имейте также в виду, что событие кнопки Click возникает при нажатии клавиши ВВОД.

См. также

Задачи

Практическое руководство. Поддержка COM-взаимодействия путем отображения формы Windows Forms с помощью метода ShowDialog

Пошаговое руководство. Поддержка COM-взаимодействия путем отображения каждой формы Windows Forms в отдельном потоке

Основные понятия

Предоставление COM-клиентам доступа к компонентам .NET Framework

Упаковка сборки для модели COM

Регистрация сборок в COM

Общие сведения о Windows Forms и неуправляемых приложениях