none
Background Worker에서 생성된 컨트롤 표시문제 RRS feed

  • 질문

  • Visual Studio 2012사용하면서 VB.net으로 프로그램을 개발하고 있는데요.

    간단한 폼이 실행되면서 미리 정해진 수에 따라 background worker를 다이나믹하게 생성하고,

    그 background worker의 DoWork을 통해 각각의 쓰레드에서 사용가능한 컨트롤들을 생성했는데,

    생성한 컨트롤들이 표시가 안되네요. 디버깅으로 해 보면 분명히 생성되어 있고 속성값들도 지정되어 있는데..

    샘플소스는 다음과 같이 간략하게 표시했는데요, 폼에 진입하면서 몇개의 독립적인 쓰레드로 실행되는 패널의

    갯수를 지정하고(ViewCount), 그 지정된 수 만큼 Backgroudn Worker를 생성하고 생성된 Worker를  실행

    해서 쓰레드에 속한 컨트롤들을 생성합니다. 그런데 이렇게 만들어진 컨트롤들이 화면에 나타나지 않습니다.

    쓰레드 없이 직접 실행하면 멀쩡히 나타나는데 말이죠. 해결 방법이 있을까요? 뭔가 잘못한 부분이 있는가요?

     

    ----------------------------------------

    Module Main

        Public Panel(7) As Panel         ' Panel
        Public PName(7) As Label       ' Panel name label
        Public ImageBox(7) As PictureBox   ' Image display pane
        Public CAMPlay(7) As PictureBox     ' Video/Photo display mode switch button

        Public ViewCount As Integer     ' 화면에 표시할 패널의 갯수

    End Module

    -----------------------------------------

    Imports System.ComponentModel

    Public Class Main

         ' Worker 목록 저장용 리스트
        Dim BGWThread As New List(Of BackgroundWorker)          ' 쓰레드 목록 저장소
        Dim WithEvents BGW As BackgroundWorker = Nothing      ' 백그라운드 워커

         Private Sub Main_Load(sender As Object, e As EventArgs) Handles MyBase.Load

            ViewCount = 2  ' 생성될 쓰레드의 갯수

            For Ix As Integer = 1 To ViewCount

                'Worker 생성
                BGW = New BackgroundWorker

                '이벤트 할당
                AddHandler BGW.DoWork, AddressOf Thread_DoWork

                'Woker를 리스트에 추가
                BGWThread.Add(BGW)
                BGW.WorkerSupportsCancellation = True
                BGW.WorkerReportsProgress = True

                 BGWThread.Item(Ix - 1).RunWorkerAsync(Ix)  ' 해당 Background Worker 실행
            Next

        End Sub

         '백그라운드 워커의 쓰레드 실행루틴
        Private Sub Thread_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs)

            ' e.Argument를 통해 원하는 내용 전송

            Dim myBGW As BackgroundWorker = DirectCast(sender, BackgroundWorker)

            AddNewControl(e.Argument)   ' 해당 쓰레드에서 사용가능한 컨트롤 생성
            PanelControlSize(e.Argument) ' 생성된 컨트롤의 사이즈와 위치 지정

            Do While True

                ' 이곳에는 카메라 스트림이 이미지에 뿌려지는 루틴을 계속 수행합니다.

            Loop

        End Sub

        ' 백그라운드워커의 DoWork을 통해 새로운 컨트롤 생성

        Private Sub AddNewControl(CI As Integer)

            ' 컨트롤을 생성
            Panel(CI) = New Panel
            PName(CI) = New Label
            ImageBox(CI) = New PictureBox
            CAMPlay(CI) = New Button

            With Panel(CI)
                .Controls.Add(PName(CI))  ' 패널에 레이블 할당
                .Controls.Add(ImageBox(CI)) ' 패널에 이미지박스 할당
                .Controls.Add(CAMPlay(CI))  ' 패널에 버튼 할당

                ' 버튼의 이벤트 핸들러 할당
                AddHandler CAMPlay(CI).MouseDown, AddressOf Me.Button_Press
                AddHandler CAMPlay(CI).MouseUp, AddressOf Me.Button_Up
            End With

        End Sub

         ' 백그라운드워커의 DoWork을 통해 생성된 컨트롤들의 위치와 사이즈 지정

        Private Sub PanelControlSize(CI As Integer)

            With Panel(CI)
                .Width = 100

                .Height = 100

                .Top =1
                .Left = CI * 150

                 ' 패널의 이름 표시 레이블

                With PName(CI)
                    .Width = 100

                    .Height = 10
                    .Left = 3
                    .Top = 0
                    .Text = "패널" & CStr(CI)
                End With

                ' 패널에 표시될 이미지박스

                With ImageBox(CI)
                    .Width = 95
                    .Height = 60

                    .Left = 3
                    .Top = 10

                    .Image = My.Resources.UNLINKED
                End With

                 ' 작업을 수행할 버튼

                With CAMPlay(CI)
                    .Width = 80

                    .Height = 20

                    .Left = 60

                    .Top = 75

                    .Text = "실행"
                End With

             End With

        End Sub

        ' 버튼에 할당된 작업
        Private Sub Button_Press(sender As Object, e As EventArgs)

             ' 마우스로 버튼을 눌렀을때 수행할 루틴

        End Sub

        Private Sub Button_Up(sender As Object, e As EventArgs)

            ' 마우스 버튼을 놓았을때 수행할 루틴

        End Sub


    End Class



    2014년 8월 21일 목요일 오전 8:33

답변

  • 일단 BackgroundWorker 개체의 완료될때의 이벤트(RunWorkerCompleted)를 생성해주고 나서

    Me.Controls.Add를 호출해서 해당 숫자에 맞는 Panel 개체를 추가해주시면 됩니다.

    동적으로 생성되는 컨트롤은 폼 컨트롤에 추가해주지 않으면 화면에 표시되지 않습니다.


    Hong-ju

    2014년 8월 22일 금요일 오후 2:12

모든 응답

  • 일단 BackgroundWorker 개체의 완료될때의 이벤트(RunWorkerCompleted)를 생성해주고 나서

    Me.Controls.Add를 호출해서 해당 숫자에 맞는 Panel 개체를 추가해주시면 됩니다.

    동적으로 생성되는 컨트롤은 폼 컨트롤에 추가해주지 않으면 화면에 표시되지 않습니다.


    Hong-ju

    2014년 8월 22일 금요일 오후 2:12
  • 쓰레드가 계속 유지되어야 하는 상황에서는 사용이 불가능하군요.

    결국은 해당 컨트롤들을 폼에 먼저 표시하고 쓰레드에서는 대리자 호출을 통해 사용하는 방법 외에는

    없군요. 쓰레드가 유지되고 있을때는 UI 변경이 크로스 쓰레드가 되어 사용이 불가능하니...


    2014년 8월 25일 월요일 오전 3:12