I'm having trouble using threading in a VB.net application I'm writing. I have a really simple version here to illustrate the problem I'm having.
It works perfectly if I load my form and have the VNC control connect to my VNC server as a single thread application using this code:
Imports VncSharp
Imports System.Windows.Forms
Imports System.ComponentModel
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
If Not RemoteDesktop1.IsConnected Then
Dim Host As String = "10.0.0.1"
RemoteDesktop1.Connect(Host)
End If
End Sub
End Class
In order to make the connection occur in the background, this is the code I've tried using the backgroundworker control. I followed the information in this article to handle referencing the controls on the form using an instance, but I still get an error when it tries to use the VNCSharp control (RemoteDesktop1) to connect to a VNC server at the line:
Instance.RemoteDesktop1.Connect(Host)
The error is:
System.InvalidOperationException: 'Cross-thread operation not valid: Control 'RemoteDesktop1' accessed from a thread other than the thread it was created on.'
Here's the code:
Imports VncSharp
Imports System.Windows.Forms
Imports System.ComponentModel
Public Class Form1
'Taken from https://stackoverflow.com/questions/29422339/update-control-on-main-form-via-background-worker-with-method-in-another-class-v
Private Shared _instance As Form1
Public ReadOnly Property Instance As Form1
Get
Return _instance
End Get
End Property
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
_instance = Me
BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
System.Threading.Thread.Sleep(1000)
If Not Instance.RemoteDesktop1.IsConnected Then
Dim Host As String = "10.0.0.1"
Instance.RemoteDesktop1.Connect(Host)
'Connect()
End If
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
MsgBox("BG1 complete")
End Sub
End Class
I figured it out - one part of the code in the post I linked to on threading held the answer: I needed to use Invoke() to reference the form RemoteDesktop control:
Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
System.Threading.Thread.Sleep(1000)
If Not Instance.RemoteDesktop1.IsConnected Then
Me.Instance.Invoke(Sub()
Dim Host As String = "10.61.41.7"
Me.RemoteDesktop1.Connect(Host)
End Sub)
End If
End Sub
instead of just putting Instance.RemoteDesktop1.Connect(Host)
Related
I would like to share an event to another form via a common class with a public shared event.
My code is setup like this:
Form1 is the main form where the button.click event is generated
Form2 is a subform displayed in Form1 in a panel control, where if the event is generated executes a sub.
To share data I use a commonData class, to share the only data i need, because I want to keep private function and variables in the single forms.
Can someone help me figure out what I'd like to do?
something like this, but working
Public Class commonData
Public Shared Event event1()
End class
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles button1.Click
RaiseEvent commonData.event1()
End Sub
End class
Public Class Form2
Private Sub eventFired(sender As Object, e As EventArgs) Handles commonData.event1
MsgBox("event")
End Sub
End class
There is many techniques to do that but this one (which is one of those) I hope might help you to have an idea how can have a shared Event between Forms or other classes.
First as you want here is the common module (you can use a class instead, is your choice; but <Extension()> go only in modules).
CommonData as a Class and ExtensionUtils as a Module for extensions:
Imports System.Runtime.CompilerServices
Public Class CommonData
Public Shared Event MyGlobalEvent(eventSender As Object, otherParams As String)
Shared Sub RaiseMyGlobalEvent(eventSender As Object, otherParams As String)
RaiseEvent MyGlobalEvent(eventSender, otherParams)
End Sub
End Class
Module ExtensionUtils
<Extension()>
Public Sub ButtonClick(ByVal buttonCaller As Button, eventArgs As String)
CommonData.RaiseMyGlobalEvent(buttonCaller, eventArgs)
End Sub
End Module
And here the implementation:
In this example I use a button named “Button1” in Form2 and when I click on it show a msgbox in Form1.
Form1:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Form2.Show()
AddHandler CommonData.MyGlobalEvent, Sub(objSender As Object, message As String)
MsgBox(message & vbCrLf & " But I'm telling you that from form " & Me.Name)
End Sub
End Sub
End Class
Form2:
Public Class Form2
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
AddHandler Button1.Click, Sub()
Button1.ButtonClick(("I'm clicked from form " & Me.Name))
End Sub
End Sub
End Class
I am working on making my own game, and I want to implement a custom DLL that I have made. It uses custom Public Sub arguments, and it seems that I can't implement it properly. The code for the DLL goes like this:
Public Class EventChanger
Public Sub StopEvent()
'code here to stop event
End Sub
Public Sub StartEvent()
'code here to start event
End Sub
End Class
I compiled it, and added the reference to it, and added the code to it.
Imports EventChanger
And when I make the code it looks like this:
Imports EventChanger
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
EventChanger.EventChanger.StopEvent()
'other code
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
'other code unrelated to event
End Sub
End Class
I get a error like this, so then I tried this:
Imports EventChanger
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
EventChanger.StopEvent()
'other code
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
'other code unrelated to event
End Sub
End Class
But I still get an error. Could someone help me? Thanks!
Changing the code to
Public Class EventChanger
Public Shared Sub StopEvent()
'code here to stop event
End Sub
Public Shared Sub StartEvent()
'code here to start event
End Sub
End Class
Worked. Now I can do the following code:
Imports EventChanger
And when I make the code it looks like this:
Imports EventChanger
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
EventChanger.EventChanger.StopEvent()
'other code
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
'other code unrelated to event
End Sub
End Class
This works for me.
Could someone please guide me as to how I would get this actually working? Currently it gives me errors about WithEvents - although simplified it shows the form - but I have no clue what that actually means. It's an toolbox I'm making just to allow the user to better interact with some of my other code.
All I need is the form visuals/guts to be custom, but then the code to be done within my application (which doesn't have visual editing capabilities).
Is this a case where I need to use interfacing/partial classes/inheritance, or can this easily be accomplished with just some minor tweaking to what I have?
(Form created in visual studio form designer and then changed to a class library. Application code written in Autodesk Inventor "rule" environment)
Thanks!
Application code:
AddReference "C:\Users\Documents\Visual Studio 2013\Projects\WindowsApplication1\WindowsApplication1\bin\Release\SectionSymToolBox.dll"
Imports System.Windows.Forms
Public Class SectionSymRule
'Public dlg As New System.Windows.Forms.For
Public Shared ToolBox As New SectionSymToolBox.SectionSymToolBox
Dim WithEvents EClass As New EventClass
Sub Main()
ToolBox.Show()
End Sub
End Class
Form code:
Public Class SectionSymToolBox
Private Sub Main()
End Sub
Public Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
'Swap Symbols
End Sub
Public Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Flip Symbol
End Sub
Public Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
'Flip Text
End Sub
Public Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
'<
End Sub
Public Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
'>
End Sub
End Class
Is this what you are looking for?
AddHandler ToolBox.Button1.Click, AddressOf HandlerMethodHere
Where HandlerMethod is a method that has the same signature as Button1.Click so for example:
Private Sub HandleButton1Click(sender As Object, e As EventArgs)
'Code here
End Sub
Obviously, replace Button1 with the name of the button.
I'm wanting to use visual studio to create a form with buttons, but then have it coded elsewhere, so that I can use the events (ie; button clicks) to perform specific actions in this application.
Is it possible/practical to do this? If not/if so, what do I need to look up and learn about from here to be able to implement it? My knowledge base in programming is limitted; I've just been starting to get familiar with Classes.
(I'm working in Autodesk Inventor, and am trying to create a prompt window with buttons to control the output of another program I have. In order to save on the amount of calls/interfacing, I was hoping to just create an uncoded button form, but code it within my program/macro I have within Inventor - its to be a form with six buttons that end up rotating some graphics within the program at a certain stop point, and then the program resumes when the form is closed via the "x")
I have seen posts such as the one below, but that doesn't seem to have the capability to receive user input: How to create a custom MessageBox?
Currently I am here, which works for showing the toolbox. Can someone show me how I would handle the events please?
AddReference "C:\Users\Documents\Visual Studio 2013\Projects\WindowsApplication1\WindowsApplication1\bin\Release\SectionSymToolBox.dll"
Imports System.Windows.Forms
Public Class SectionSymRule
'Public dlg As New System.Windows.Forms.For
Public Shared ToolBox As New SectionSymToolBox.SectionSymToolBox
Dim WithEvents EClass As New EventClass
Sub Main()
ToolBox.Show()
End Sub
End Class
Public Class SectionSymToolBox
Private Sub Main()
End Sub
Public Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
'Swap Symbols
End Sub
Public Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Flip Symbol
End Sub
Public Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
'Flip Text
End Sub
Public Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
'<
End Sub
Public Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
'>
End Sub
End Class
You can always use Partial Class to split your code into multiple files.
So you create your Form (say Form1) the normal way. Then put the code in another class file with class declared as Partial
For example,
Partial Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
MsgBox(TextBox1.Text)
End Sub
End Class
The other way is to inherit your Form. The inherited form will then have everything of whatever is on the form, with whatever you want to add.
Public Class Form1Code
Inherits Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
MsgBox(TextBox1.Text)
End Sub
End Class
I downloaded GeckoFX (ver 16), the XULRunner Dotnet wrapper to use in a winForms (VB.NET) application, but there are no instructions on usage anywhere (just the Initialize command).
I added the control onto my form and in the Form load event, put in the following:
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Xpcom.Initialize(My.Application.Info.DirectoryPath & "/xulrunner")
InitializeComponent()
Me.GeckoWebBrowser1.Enabled = True
Me.GeckoWebBrowser1.Navigate("http://www.google.com")
End Sub
Nothing happens. The control is not visible, no navigation takes place.
Just a simple project (C# is fine too) that shows the control actually working would be nice (please do not answer with another URL that points to GeckoFx's wiki page as it is useless and no examples anywhere are shown)
Imports Gecko
Public Class Form1
Private myBrowser As GeckoWebBrowser
Public Sub New()
InitializeComponent()
Xpcom.Initialize(My.Application.Info.DirectoryPath & "\xulrunner")
myBrowser = New GeckoWebBrowser()
myBrowser.Parent = Me.SplitContainer1.Panel2
myBrowser.Dock = DockStyle.Fill
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
myBrowser.Navigate(TextBox1.Text)
End Sub
End Class
Just do it with Events. Im talking for withEvents:D
Imports Gecko
Public Class Form1
Private WithEvents myBrowser As GeckoWebBrowser
Public Sub New()
InitializeComponent()
Xpcom.Initialize(My.Application.Info.DirectoryPath & "\xulrunner")
myBrowser = New GeckoWebBrowser()
myBrowser.Parent = Me.SplitContainer1.Panel2
myBrowser.Dock = DockStyle.Fill
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
myBrowser.Navigate(TextBox1.Text)
End Sub
End Class