2016-08-26 5 views
0

메인 스레드에 NumericUpDown 컨트롤이 있습니다.BackgroundWorker 및 공유 클래스

나는 NumericUpDown 값을 저장하는 공개 class_A의 인스턴스를 만듭니다.

별도의 스레드를 실행하는 BackgroundWorker을 만듭니다.

BackgroundWorker 스레드에서 class_A의 인스턴스에서 인수를 호출하는 class_B의 인스턴스를 만듭니다.

class_A의 인스턴스가 방금 전에 생성 된 결과가 Nothing 인 이유를 알 수 없습니다. 여기

코드입니다 :

Imports System.ComponentModel 
Public Class Form1 
    Dim WithEvents bgw As New BackgroundWorker 
    Dim WithEvents bgw2 As New BackgroundWorker 
    Dim lSide As Label 
    Public nudSide As NumericUpDown 
    Dim bCalculate As Button 
    Dim bCalculate2 As Button 
    Dim tbLog As TextBox 
    Dim calc As calc 
    Public calc2 As calc2 
    Public Delegate Function d_getSide() As Double 
    Public getSide As New d_getSide(AddressOf rungetSide) 
    Public Side As c_Side 
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load 
     Me.Size = New Size(400, 160) 
     bgw.WorkerSupportsCancellation = True 
     bgw2.WorkerSupportsCancellation = True 

     lSide = New Label 
     With lSide 
      .Text = "Side" 
      .Size = New Size(40, 20) 
      .Location = New Point(10, 10) 

     End With 
     Me.Controls.Add(lSide) 
     nudSide = New NumericUpDown 
     With nudSide 
      .Size = New Size(40, 20) 
      .Location = New Point(lSide.Location.X + lSide.Size.Width, lSide.Location.Y) 
      .DecimalPlaces = 0 
      .Minimum = 1 
      .Maximum = 100 
      .Increment = 1 
      .Value = 1 
     End With 
     Me.Controls.Add(nudSide) 
     bCalculate = New Button 
     With bCalculate 
      .Text = "Calculate" 
      .Size = New Size(60, 20) 
      .Location = New Point(nudSide.Location.X + nudSide.Size.Width + 40, nudSide.Location.Y) 
      AddHandler .Click, AddressOf bCalculate_Click 
     End With 
     Me.Controls.Add(bCalculate) 
     bCalculate2 = New Button 
     With bCalculate2 
      .Text = "Calculate 2" 
      .Size = New Size(60, 20) 
      .Location = New Point(bCalculate.Location.X + bCalculate.Size.Width + 10, bCalculate.Location.Y) 
      AddHandler .Click, AddressOf bCalculate2_Click 
     End With 
     Me.Controls.Add(bCalculate2) 

     tbLog = New TextBox 
     With tbLog 
      .Size = New Size(250, 60) 
      .Location = New Point(lSide.Location.X, lSide.Location.Y + 40) 
      .Multiline = True 
      .ScrollBars = ScrollBars.Vertical 

     End With 
     Me.Controls.Add(tbLog) 

    End Sub 
    Private Sub bCalculate_Click() 
     bgw.RunWorkerAsync(nudSide.Value) 
    End Sub 
    Private Sub bgw_Dowork(sender As Object, e As DoWorkEventArgs) Handles bgw.DoWork 
     'example 1) 
     'passing argument throught backGroundWorker 
     calc = New calc(e.Argument) 
    End Sub 
    Private Sub bgw_Runworkercompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles bgw.RunWorkerCompleted 
     getResult() 
    End Sub 
    Private Sub bCalculate2_Click() 
     'here i create an instance of the Side class (expose the side property) 
     Side = New c_Side 
     bgw2.RunWorkerAsync() 
    End Sub 
    Private Sub bgw2_Dowork(sender As Object, e As DoWorkEventArgs) Handles bgw2.DoWork 
     'example 2) 
     ' in the backgroundworker thread i create an instance of the class calc2 
     calc2 = New calc2() 
    End Sub 
    Private Sub bgw2_Runworkercompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles bgw2.RunWorkerCompleted 
     getResult2() 
    End Sub 
    Private Sub write(ByVal message As String) 
     With tbLog 
      .SelectionStart = .Text.Length 
      .SelectedText = vbCrLf & message 
     End With 
    End Sub 
    Private Sub getResult() 
     tbLog.Clear() 
     write("area = " & calc.area & " cm^2") 
     write("volume = " & calc.volume & " cm^3") 

    End Sub 
    Private Sub getResult2() 
     tbLog.Clear() 
     write("area = " & calc2.area & " cm^2") 
     write("volume = " & calc2.volume & " cm^3") 

    End Sub 
    Public Function rungetSide() As Double 
     If Me.InvokeRequired Then 
      Me.Invoke(getSide) 
     Else 
      Return Side.Side 
     End If 
     Return Side.Side 
    End Function 
End Class 
Class calc 
    Sub New(ByVal Side As Double) 
     _area = Side^2 
     _volume = Side^3 
    End Sub 
    Private _area As Double 
    Public Property area As Double 
     Get 
      Return Math.Round(_area, 2) 
     End Get 
     Set(value As Double) 
      _area = Math.Round(value, 2) 
     End Set 
    End Property 
    Private _volume As Double 
    Public Property volume As Double 
     Get 
      Return Math.Round(_volume, 2) 
     End Get 
     Set(value As Double) 
      _volume = Math.Round(value, 2) 
     End Set 
    End Property 
End Class 
Public Class calc2 
    Sub New() 
     'the constructor, recall the value from the instance (public) of the class 'Side' just built in the main thread 
     'but i don't understand why the instance it's nothing 
     _area = Form1.Side.Side^2 
     _volume = Form1.Side.Side^3 
    End Sub 
    Private _area As Double 
    Public Property area As Double 
     Get 
      Return Math.Round(_area, 2) 
     End Get 
     Set(value As Double) 
      _area = Math.Round(value, 2) 
     End Set 
    End Property 
    Private _volume As Double 
    Public Property volume As Double 
     Get 
      Return Math.Round(_volume, 2) 
     End Get 
     Set(value As Double) 
      _volume = Math.Round(value, 2) 
     End Set 
    End Property 
End Class 
Public Class c_Side 
    Sub New() 
     _Side = Form1.nudSide.Value 
     '_Side = Form1.rungetSide 
    End Sub 
    Private _Side As Double 
    Public Property Side As Double 
     Get 
      Return Math.Round(_Side, 2) 
     End Get 
     Set(value As Double) 
      _Side = Math.Round(value, 2) 
     End Set 
    End Property 
End Class 

내가 무엇을 찾고 있어요 것은 NumericUpDown 값을 메인 스레드에서 class_A의 인스턴스를 생성하고 저장할 수 있으며, 별도의 스레드에서 (BackgroundWorker)의 인스턴스를 생성 class_B의 인스턴스에 저장하기 직전에 NumericUpDown 컨트롤의 값을 가져옵니다.

+0

@SirRufo : 하나의 태그를 제거하는 것과 같이 사소한 편집을하지 마십시오. 특히 다른 사람이 실제로 게시물을 크게 개선하는 편집 작업을하는 비교적 새로운 게시물에 특히주의하십시오. 소식을 수정해야한다고 생각되면 수정이 필요한 _everything_을 수정하십시오. 그렇지 않으면 진행중인 편집을 중단하고 다시 편집해야합니다. –

+0

미안 .. ?? 내 메시지를 편집하지 않아. – Marcello

+1

'Form1.nudSide'. 한숨, VB.NET은 VB.NET 프로그래머가 스레드 된 코드를 제대로 작성할 수 없도록 설계되었습니다. 이 표현식은 작업자 스레드에서 호출 될 때 Form1 클래스의 * 새 인스턴스를 만듭니다. 작업자 스레드에서 UI 구성 요소에 절대 액세스하지 마십시오. bCalculate_Click()에서 올바르게 수행 한 방법에 유의하십시오. –

답변

-1

해결책을 찾았습니다. 그냥 모든 스레드에서, 그래서

Public Shared Side As c_Side 

그래서 그것은 모든 응용 프로그램에서 볼 수의 공용 공유로 변수를 선언합니다. 그래서 내가 스레드를 시작할 때 (또는 필요할 때 필요할 때), backGroundWorker 스레드에서 '읽을 수있는'공용 클래스의 공용 공유 인스턴스에서 UI 컨트롤의 모든 값을 백업합니다.