I am trying to call the function getTemp(value as integer) from my webservice service1. When I execute the code it gives an error saying that _value is nothing.
If I call the same function in a normal windowsforms project it runs perfectly.
Does anyone have a solution ?
See my code below (import statements omitted):
Dim _value As String
Private Sub Button_Click_1(sender As Object, e As RoutedEventArgs)
Dim client As New Service1Client
AddHandler client.GetTempCompleted, AddressOf getTempgotten
client.GetTempAsync(3)
MessageBox.Show(CStr(_value))
End Sub
Public Sub getTempgotten(sender As Object, e As GetTempCompletedEventArgs)
_value = CStr(e.Result)
End Sub
PS: I'm new to this forum, so forgive my mistakes.
Related
The objective in this question is to create a code block that executes when a datatable has changed content (just the fact that it has changed, not the specific row/column etc). This is VB Winforms NET.
This works:
Public Class Form1
Sub testhandler()
Dim locallyDeclaredDT as new datatable
AddHandler locallyDeclaredDT.ColumnChanged, New DataColumnChangeEventHandler(AddressOf Column_Changed)
End Sub
Private Shared Sub Column_Changed(sender As Object, e As DataColumnChangeEventArgs)
MessageBox.Show("The table has changed")
End Sub
End Class
But I need a datatable that is accessible outside of the sub's scope so I try this, which doesn't work.
Public Class Form1
Dim globallyDeclaredDT as new datatable
Sub testhandler()
AddHandler globallyDeclaredDT.ColumnChanged, New DataColumnChangeEventHandler(AddressOf Column_Changed)
End Sub
Private Shared Sub Column_Changed(sender As Object, e As DataColumnChangeEventArgs)
MessageBox.Show("The table has changed")
End Sub
End Class
The problem is caused by the AddHandler line: the ColumnChanged property is underlined and the error is
'ColumnChanged' is not an event of 'Object'.
How can I fix this?
I am in a project with multiple form.
I create a TicTacToe form here :
Private Sub MenuTicTacToe(ByVal sender As Object, ByVal e As System.EventArgs)
Dim page As Form = New TicTacToe
page.Show(Me)
End Sub
Here is a TicTacToe form:
Public Class TicTacToe
Public opponent as String
'Some code where user set opponent
Public Function Receive(S As String)
if string = opponent
'Some code
End Function
End Class
I would like to call my function Receive in my main form
If i do:
TicTactoe.Receive(S)
It call a instance of Receive where opponent does not exist.
I would like to find the oppened form of TicTacToe and call Receive
Thanks
Comments in line
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
page.Receive("Joe")
End Sub
'A form level variable to hold a reference to the instance of TicTacToe
'Although vb.net can use default instances, you have created an explicit
'instance of TicTacToe so you need to keep a reference if you want to
'refer to this instance.
Private page As TicTacToe
Private Sub MenuTicTacToe(ByVal sender As Object, ByVal e As System.EventArgs)
page = New TicTacToe()
page.Show(Me)
End Sub
Partial Public Class TicTacToe
Inherits Form
Public opponent As String
'Functions must be declared as a Type
'If you do not need a return value use a Sub
Public Function Receive(S As String) As String
Dim someString As String = ""
If S = opponent Then
'Do something
End If
'There must be a return Value
Return someString
End Function
End Class
Use this to show the form
Dim page As TicTacToe
Private Sub MenuTicTacToe(ByVal sender As Object, ByVal e As System.EventArgs)
page = New TicTacToe
page.Show(Me)
End Sub
Then you can use
page.Receive(S)
Edit
To use multiple forms
For Each f As TicTacToe in Application.OpenForms().OfType(Of TicTacToe)
f.Receive (S)
Next
In C#, you'd need a new instance, but as you are in VB, the compiler already does that for you.
What you are currently doing, is creating a new instance of the TicTacToe form and showing it:
Private Sub MenuTicTacToe(ByVal sender As Object, ByVal e As System.EventArgs)
Dim page As Form = New TicTacToe
page.Show(Me)
End Sub
But you don't save that instance anywhere. Then, in your next piece of code, you are using a different instance, which is the static one created by the compiler:
TicTacToe.Receive(S) // TicTacToe is the static instance
Therefore, you end up calling two different instances, which explains why there is no opponent set.
To get around this problem, do not create a new instance. In your Private Sub MenuTicTacToe, just use the instance created by the compiler, and you won't have this problem, just like this:
Private Sub MenuTicTacToe(ByVal sender As Object, ByVal e As System.EventArgs)
TicTacToe.Show(Me)
End Sub
Hope this helps.
Long story short, I'm having a hell of a time trying to figure out how to use invoke and/or delegates to update the userform from a separate class when using threading. I'm quite sure it's something silly and obvious to someone with more experience. I know a delegate is probably required, but all my efforts seem to only work when it's being called from main thread. I've been looking around the internet for half the day, and there's just something I'm not getting.
Here's some pseudo-code as an example:
This option works:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim t1 As New Threading.Thread(AddressOf Count)
t1.IsBackground = True
t1.Start(100)
End Sub
Private Sub Count(ByVal Max As Object)
If TypeOf Max Is Integer Then
Count(CInt(Max))
End If
End Sub
Private Sub SetLabelText(ByVal text As String)
If Label1.InvokeRequired Then
Label1.Invoke(New Action(Of String)(AddressOf SetLabelText), text)
Else
Label1.Text = text
End If
End Sub
Private Sub Count(ByVal Max As Integer)
For i = 1 To Max
SetLabelText(CStr(i))
Threading.Thread.Sleep(200)
Next
End Sub
End Class
While this (one of my 1000 efforts of slightly different variation) does not. Practically speaking, I just tried to separate one of the subs into its own class for this example, but it's otherwise the same as I could make it:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim t1 As New Threading.Thread(AddressOf Count)
t1.Start(100)
End Sub
Private Sub Count(ByVal Max As Object)
If TypeOf Max Is Integer Then
Dim class2 As New class2
class2.Count(CInt(Max))
End If
End Sub
Private Delegate Sub SetTextBoxTextInvoker(text As String)
Sub SetLabelText(ByVal text As String)
'or me.label1, form1.label1 or anything else I can try!
If Me.InvokeRequired Then
Me.Invoke(New SetTextBoxTextInvoker(AddressOf SetLabelText), _
text)
Else
Me.Label1.Text = text
End If
End Sub
End Class
Public Class class2
Sub Count(ByVal Max As Integer)
For i = 1 To Max
form1.SetLabelText(CStr(i))
Threading.Thread.Sleep(200)
Next
End Sub
End Class
From what I can tell, it appears that the if statement for invokerequired in the Sub "SetLabelText" never gets triggered. My best guess is that I'm not referring to the userform correctly when checking for the invokerequired parameter? Or I need to feed something else to the delegate? I'm just getting frustrated with messing around with the million little variables I might be getting wrong. Thanks in advance for any help you can provide and let me know if you need more info.
I'm not certain I understand what you are trying to do, but building upon your code, you can set the label safely ("thread-safely") by using the following code:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim t1 As New Threading.Thread(AddressOf Count)
t1.IsBackground = True
t1.Start(100)
End Sub
Private Sub Count(ByVal Max As Object)
If TypeOf Max Is Integer Then
Dim class2 As New Class2
class2.Count(CInt(Max), AddressOf SetLabelText)
End If
End Sub
Private Sub SetLabelText(ByVal text As String)
If Label1.InvokeRequired Then
Label1.Invoke(New SetText(AddressOf SetLabelText), text)
Else
Label1.Text = text
End If
End Sub
End Class
Public Class Class2
Sub Count(ByVal Max As Integer, SetTextMethod As SetText)
For i = 1 To Max
SetTextMethod.Invoke((CStr(i)))
Threading.Thread.Sleep(200)
Next
End Sub
End Class
Public Delegate Sub SetText(text As String)
I created a Delegate called "SetText"; when the form calls the count function in your class, you can pass an instance of the delegate that references the SetLabelText method. Within that method you can then safely set the label text either directly or indirectly via Invoke along with a new instance of the delegate.
Something you definitely don't want to do is reference your form from your class(i.e. "form1.SetLabelText(CStr(i))"); that can create a real nightmare as the project grows in size and requirements change!
If I've misunderstood your question or not answered it properly, please do post back.
First off I would suggest using the Task Parrallel Library instead of threads. It's easier to understand and work with. For example,
Dim countTask as New Task(Sub() Count(10))
Dim displayTask = countTask.ContinueWith(Sub()
Me.Invoke(Sub() Label.Text = "10"
End Sub)
countTask.Start()
This example assumes you are calling this from the form itself. You can use this method to return values from the first task to the second. If you need a more detail example and want more examples check out http://msdn.microsoft.com/en-us/library/hh228603.aspx. If you need further help I can always throw something up on GitHub or blog about it. Good Luck.
Please have a look at the code below:
Public Delegate Sub TestButtonClick(ByVal test As Integer)
Public Class Person
Private Name As String
Private ID As Integer
Public Event ButtonClick As TestButtonClick
Public Sub DelegateTest1(ByVal Test As Integer)
MsgBox(Test)
End Sub
Public Sub ChangeName()
RaiseEvent ButtonClick(1)
End Sub
Public Sub DelegateTest2()
MsgBox("Delegate Test 2")
End Sub
Public Sub DelegateTest3()
MsgBox("Delegate Test 3")
End Sub
End Class
Public Class Form1
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim p1 As Person = New Person
AddHandler p1.ButtonClick, AddressOf p1.DelegateTest1
AddHandler p1.ButtonClick, AddressOf p1.DelegateTest2
AddHandler p1.ButtonClick, AddressOf p1.DelegateTest3
p1.ChangeName()
End Sub
End Class
The output is:
1
DelegateTest2
DelegateTest3
I do not understand why this application compiles i.e. the delegate accepts an integer in its signature but Person.DelegateTest2 and Person.DelegateTest3 do not.
If I change Person.DelegateTest2() to the following then I do get an error as I would expect:
Public Sub DelegateTest2(ByVal Test As Integer, ByVal Test2 As Integer)
MsgBox("Delegate Test 2")
End Sub
Why does the Delegate allow you to pass zero arguments when it has arguments i.e. an integer in my case?
Don't forget that VB.NET inherits all the legacy baggage from the beloved VB. You could make it strict by putting the following to the top of your file so that it behaves as a real .NET programming language and not some hybrid crap:
Option Strict On
Also I would recommend you setting this to be the default option so that you don't find yourself in the wilderness.
I am creating a very simple state machine class library project in vb.net.
This has only 3 states - CreateApplication, ProcessApplication and CompleteApplication.
I have an interface created in the same project.I am invoking it from a web application by calling ApplicationService.CreateApplication(obj of ApplicationDetail)
<ExternalDataExchange()> _
Public Interface IApplicationService
Event ApplicationCreated As EventHandler(Of ApplicationDetailEventArgs)
Event ApplicationProcessed As EventHandler(Of ApplicationDetailEventArgs)
End Interface
I also have its implementation in ApplicationService.vb
Public Class ApplicationService
Implements IApplicationService
Public Event ApplicationCreated(ByVal sender As Object, ByVal e As ApplicationDetailEventArgs) Implements IApplicationService.ApplicationCreated
Public Event ApplicationProcessed(ByVal sender As Object, ByVal e As ApplicationDetailEventArgs) Implements IApplicationService.ApplicationProcessed
Public Shared Sub CreateApplication(ByVal objApplicationDetail As ApplicationDetail)
Using workflowRuntime As New WorkflowRuntime()
AddHandler workflowRuntime.WorkflowCompleted, AddressOf OnWorkflowCompleted
AddHandler workflowRuntime.WorkflowTerminated, AddressOf OnWorkflowTerminated
Dim workflowInstance As WorkflowInstance
workflowInstance = workflowRuntime.CreateWorkflow(GetType(Workflow1))
workflowInstance.Start()
End Using
'Code to create application
End Sub
Shared Sub OnWorkflowCompleted(ByVal sender As Object, ByVal e As WorkflowCompletedEventArgs)
End Sub
Shared Sub OnWorkflowTerminated(ByVal sender As Object, ByVal e As WorkflowTerminatedEventArgs)
End Sub
End Class
My issueis that, when I try to run it I am getting the value of workflowInstance . InstanceId as Empty.
I have been trying to fix this since the last 2 days.
Can someone please help.
Thanks in advance!
Well..I was able to figure out what the problem was.
It has nothing to do with workflow. It is a bug in Visual Studio(2005 and 2008). When you debug in VB.Net, the value of a Guid shows up as empty, but if you use Guid.ToString..it works fine. This does work correctly in C#.