[RESOLVED] Invoking many controls
Hello,
The function below will be called from another thread. So the control themselves will have to be invoked so that the correct thread that created them can change the properties.
However, as I have many controls that need to be updated. I don't really want to write all those delegates for each one. I have done one below. However, I am thinking that is a lot of code. Is there anyway to shorten this?
Many thanks,
Code:
Public Sub SetIdleState(ByVal callStatusMsg As String)
Me.btnCallAnswer.Text = CATWinSIP_MsgStrings.Call
Me.btnEndCallReject.Text = CATWinSIP_MsgStrings.EndCall
Me.btnHoldUnhold.Text = CATWinSIP_MsgStrings.Hold
Me.btnCallAnswer.Enabled = True
Me.btnRedial.Enabled = True
Me.btnEndCallReject.Enabled = False
Me.btnHoldUnhold.Enabled = False
If Me.statusDisplay1.InvokeRequired Then
statusDisplay1.Invoke(New UpdateCallStatusDelegate(AddressOf Me.UpdateCallStatus), callStatusMsg)
Else
Me.statusDisplay1.CallStatus = callStatusMsg
End If
End Sub
' Delegate for marshalling the call on the correct thread.
Private Delegate Sub UpdateCallStatusDelegate(ByVal callStatusMsg As String)
Private Sub UpdateCallStatus(ByVal callStatusMsg As String)
Me.statusDisplay1.CallStatus = callStatusMsg
End Sub
Re: Invoking many controls
I don't understand your code. The fact that you're testing InvokeRequired in your SetIdleState method implies that that method is called on a secondary thread, yet you're accessing multiple controls in that method. Have you read the Controls & Multi-threading thread of mine in the CodeBank? It outlines a number of steps you can perform and those steps NEVER change. The fact that you have multiple controls to access is irrelevant. The steps are:
1. Write a method that does what you need:
vb.net Code:
Public Sub SetIdleState(ByVal callStatusMsg As String)
Me.btnCallAnswer.Text = CATWinSIP_MsgStrings.Call
Me.btnEndCallReject.Text = CATWinSIP_MsgStrings.EndCall
Me.btnHoldUnhold.Text = CATWinSIP_MsgStrings.Hold
Me.btnCallAnswer.Enabled = True
Me.btnRedial.Enabled = True
Me.btnEndCallReject.Enabled = False
Me.btnHoldUnhold.Enabled = False
Me.statusDisplay1.CallStatus = callStatusMsg
End Sub
2. Test the InvokeRequired property of a control, moving the current contents of the method into the Else block:
vb.net Code:
Public Sub SetIdleState(ByVal callStatusMsg As String)
If Me.InvokeRequired Then
Else
Me.btnCallAnswer.Text = CATWinSIP_MsgStrings.Call
Me.btnEndCallReject.Text = CATWinSIP_MsgStrings.EndCall
Me.btnHoldUnhold.Text = CATWinSIP_MsgStrings.Hold
Me.btnCallAnswer.Enabled = True
Me.btnRedial.Enabled = True
Me.btnEndCallReject.Enabled = False
Me.btnHoldUnhold.Enabled = False
Me.statusDisplay1.CallStatus = callStatusMsg
End If
End Sub
3. Create a delegate by copying the method declaration, changing the name and adding the Delegate key word:
vb.net Code:
Public Delegate Sub SetIdleStateInvoker(ByVal callStatusMsg As String)
Public Sub SetIdleState(ByVal callStatusMsg As String)
If Me.InvokeRequired Then
Else
Me.btnCallAnswer.Text = CATWinSIP_MsgStrings.Call
Me.btnEndCallReject.Text = CATWinSIP_MsgStrings.EndCall
Me.btnHoldUnhold.Text = CATWinSIP_MsgStrings.Hold
Me.btnCallAnswer.Enabled = True
Me.btnRedial.Enabled = True
Me.btnEndCallReject.Enabled = False
Me.btnHoldUnhold.Enabled = False
Me.statusDisplay1.CallStatus = callStatusMsg
End If
End Sub
In the If block, invoke the current method using an instance of the delegate you just declared:
vb.net Code:
Public Delegate Sub SetIdleStateInvoker(ByVal callStatusMsg As String)
Public Sub SetIdleState(ByVal callStatusMsg As String)
If Me.InvokeRequired Then
Me.Invoke(New SetIdleStateInvoker(AddressOf SetIdleState), _
callStatusMsg)
Else
Me.btnCallAnswer.Text = CATWinSIP_MsgStrings.Call
Me.btnEndCallReject.Text = CATWinSIP_MsgStrings.EndCall
Me.btnHoldUnhold.Text = CATWinSIP_MsgStrings.Hold
Me.btnCallAnswer.Enabled = True
Me.btnRedial.Enabled = True
Me.btnEndCallReject.Enabled = False
Me.btnHoldUnhold.Enabled = False
Me.statusDisplay1.CallStatus = callStatusMsg
End If
End Sub