I get an error "The type Initializer for 'Myproject' thew an exception. It's rather bizarre.
In My Main form I have the following in my Button-click event:
MyShip.Name = "Lolipop"
That one line causes the error.
MyShip is declared in a module called GlobalVariables.vb as follows:
Friend MyShip As New clsShip
clsShip has a property called Name.
I'm not sure what's happening. Oddly, I can set MyShip.Name = "Lolipop" in the form's LOAD() event, but can't do that in any of the button click events.
Ideas?
Related
In my code I use this line to Initialize my Base:
MyBase.Initialize(name, config)
Everything goes fine in the first time pass... but when it passes second time then throws me an error The Base Is already Initialized and that is something I don't want to happen.
Is there any way to catch this event?
Finally the Base initialized only in the Default.aspx page, putting these lines in the Page_Load:
Dim myNewAsp As New AspNetSqlProvider
If MyAspNetSqlMembershipProvider.SQLconnectionString = Nothing Then
myNewAsp.InitializeSite(sender, e)
Return
End If
Doing this the system always knows when if the Base is initialized or not.
How to update data in GUI with messages that are being received by a thread of another class ?
I have a class with a thread that receives data from a server. This thread raises an event whenever it gets a message from the server. This event is handled inside the Starter Class (main class which contains the GUI).
The event handler (say DisplayData() has to display the message received by the other class.
My code is like this
Class GUI
receiverObj = New Receiver()
Addhandler receiverObj.MessageAlert, Addressof DisplayData
...
...
Sub DisplayData()
Dim str As receiverObj.ReceiveData
lbEvents.Add.Items(str) ' lbEvents is a ListBox inside the GUI that displays messages from Receiver
End Sub
End Class
Class Receiver
Public Event MessageAlert()
Sub New ()
MyTcpClient = New TcpClient(hostIP, port)
MyTcpClient.GetStream.BeginRead(ReceiveData, 0, PacketSize, AddressOf ReceiveStream, Nothing)
End Sub
Public Sub ReceiveStream(ByVal ar As IAsyncResult)
Dim ByteCount As Integer
Try
ByteCount = MyTcpClient.GetStream.EndRead(ar)
Dim t As New Threading.Thread(Sub() RaiseEvent MessageAlert())
MyTcpClient.GetStream.BeginRead(ReceiveData, 0, PacketSize, AddressOf ReceiveStream, Nothing)
End Sub
End Class
The Window crashes or hangs and the listbox does not display data. Throws exception saying
Cross-thread operation not valid: Control xxx accessed from a thread other than the thread it was created on.
Can anybody suggest a way to fix this error ?
How to update data in GUI with messages that are being received by a thread of another class ?
Updates to GUI elements of a Windows application must take place on the thread that created the GUI.
To fix this, there's a method called Invoke that allows you to fire a delegate that can ensure control is passed to the GUI thread and perform the update you are attempting.
You need a few things to make this work:
A Delegate type , such as
Delegate Sub MyGUIUpdateDelegate()
A variable of the type of your delegate
Public myGUIUpdateDelegate as MyGUIUpdateDelegate
A method having a signature that matches the delegate and does the work:
Public Sub MyGuiEventHandler()
' Do work on proper GUI thread, via Control.Invoke,
' such as listbox population
If (Me.InvokeRequired) Then
Me.Invoke( myGUIUpdateDelegate)
Else
// do control specific work, we're on the GUI thread here
End If
End Sub
An assignment of the event handler to your delegate:
myGUIUpdateDelegate = New MyGuiUpdateDelegate(AddressOf myForm.MyGuiEventHandler)
A call to your updater method via Control.Invoke to the proper thread from the event thread (assuming
your form instance variable is named myForm):
myForm.Invoke(myForm.myGUIUpdateDelegate);
That's at least a framework that should help you get started. The idea is that the background thread that wants to induce the update should not (and in reality, cannot) make direct GUI updates. The proper way to initiate a context switch to the GUI thread is by calling the Invoke method to call the GUI updater on the proper GUI thread.
Additionally, if you need to pass parameters to your delegate, simply alter the signature of the Delegate you define to include the parameter(s), and modify the Invoke method to provide the arguments in the handler, and the 2nd argument to Invoke.
Hope this helps.
I've got a contributed command and a handler for it. The handler's execute event has to get the value for the property actually selected in the properties view and act on it, or to be disabled if no property selected.
I've tried:
1) Set the selection provider to something which provides selection from the property view. Something in this case is just PropertySheetViewer for my PropertySheetPage, but i can't set it as the selection provider because the PropertySheetPage's viewer is private and has no getter.
2) Overriding PropertySheetPage's createControl method: This method creates a Tree control for the PropertySheetViewer. A selection listener can be installed for that tree control, so maybe i can make my command handler implement SelectionListener... The solution would be somethin like:
In my editor:
public Object getAdapter(#SuppressWarnings("rawtypes") Class type) {
if (type == IPropertySheetPage.class) {
PropertySheetPage page = new PropertySheetPage() {
#Override
public void createControl(Composite parent) {
super.createControl(parent);
IHandler handler = someWayToGetMyCmdHandler();
((org.eclipse.swt.widgets.Tree) getControl())
.addSelectionListener(handler);
}
};
IPropertySheetEntry entry = new UndoablePropertySheetEntry(
getCommandStack());
page.setRootEntry(entry);
return page;
}
return super.getAdapter(type);
}
And my command handler implementing SelectionListener as i said... The problem with this approach is that i can't find a way to get a reference to my contributed command handler (someWayToGetMyCmdHandler() above).
Has anybody got any clue on this, or any other possible approach to the problem??
There's handleEntrySelection(ISelection selection) method in PropertySheetPage that you could override to be notified about selection changes in the viewer (although PropertySheetPage is #noextend).
The second part (updating the handler) is a bit more tricky than it would normally be. Commands/handlers get updated automatically when workbench selection changes (you just need to implement setEnabled(Object evaluationContext) AbstractHandler). But since PropertySheetPage is designed to change its input on global selection change, then you have to find some custom way to notify/update your handler.
As I understand, it is currently not possible to extend the platform command event handling mechanism with custom variables, so you just need to directly look up your handler using IHandlerService of the workbench.
I am getting a very strange error on one of my Silverlight 4.0 pages. I have a form that has a "save" button which is disabled by default. This form gets populated by a bunch of user-specified defaults, which come from an asynchronous server call (MyFacade.getFormDefaults below). When the user changes one of the fields (after it's populated), I want the "save" button to become enabled.
I think I have the logic correct, but I'm getting a very strange error that I can't find much useful information on. The error is: System.InvalidOperationException: The initialization of an object or value resulted in an object or value being accessed recursively before it was fully initialized.
Below is a very simplified version of what I have...
profile.fs:
type profile() as this =
inherit UriUserControl("/whatever;component/profile.xaml", "profile")
[<DefaultValue>]
val mutable isFormLoaded : bool
[<DefaultValue>]
val mutable btnSave : Button
[<DefaultValue>]
val mutable txtEmail : TextBox
// constructor
do
this.isFormLoaded <- false
// make the "this" values point at the XAML fields
this.btnSave <- this?btnSave
this.txtEmail <- this?txtEmail
// get the form defaults and send them to
MyFacade.getFormDefaults(new Action<_>(this.populateFormDefaults))
()
member this.populateFormDefaults (formDefaults : MyFormDefaultsUIVO array option) =
// populate this.txtEmail with the default value here
this.isFormLoaded <- true // set the form to be loaded once that's done
()
// enable the "Save" button when the user modifies a form field
member this.userModifiedForm (sender : obj) (args : EventArgs) =
// **** EXCEPTION OCCURS ON THE LINE BELOW ****
if this.isFormLoaded then
this.btnSave.IsEnabled <- true
()
profile.xaml:
<nav:Page Name="profile" Loaded="formLoaded">
<TextBox Name="txtEmail" TextChanged="userModifiedForm "/>
<Button Name="btnSave" IsEnabled="False"/>
</nav:Page>
Even if I get rid of all the isFormLoaded logic, and simply set this.btnSave.IsEnabled <- true inside of this.userModifiedForm, I get the same error. Any ideas would be greatly appreciated. Thanks.
The exception - "The initialization of an object or value resulted in an object or value being accessed recursively before it was fully initialized" - is generated by the F# runtime when an object is accessed before being fully initialized.
Accessing this - whether to check isFormLoaded or btnSave.IsEnabled - before the constructor has run will cause the error. Have you verified that userModifiedForm is only called after the constructor?
Currently I am having a weird problem which I simply do not understand. I have a simple GUI, with one button & one richeditbox. I have an async socket running, I am receiving some data over the network which I want to print to the gui(richeditbox). The async socket is being started when the user hits the button. So when I receive the network data I call a function which prints the data, here how it looks like (in form1 class):
Public Sub AddText(ByVal text As String)
Try
Console.WriteLine(text)
RichTextBox1.AppendText(text)
RichTextBox1.AppendText(vbNewLine)
Catch e As Exception
Console.WriteLine(e.ToString())
End Try
End Sub
Then I simply do Form1.AddText(..) from my network class or a module (does it matter?). The problem is that nothing appears in the richeditbox, even though the AddText function is being called, no exceptions, no errors, simply nothing. I've looked thru it with the debugger, and "text" contained the data it had to print, but simply nothing appears.. Anyone have an idea?
If the socket is running on another thread (which, of course, it is because it's asynchronous), you may have to use InvokeRequired in order to get the RichTextBox to display the text. I had a similar issue with a listener on an asynchronous serial port listener.
I'm pretty sure David is right. Here's an example.
Delegate Sub AddTextDelegate(ByVal text as String)
Public Sub AddText(ByVal text as String)
If Me.InvokeRequired Then
Me.Invoke(new AddTextDelegate(AddressOf Me.AddText), new object() { text })
Else
Try
Console.WriteLine(text)
RichTextBox1.AppendText(text)
RichTextBox1.AppendText(vbNewLine)
Catch e as Exception
Console.WriteLine(e.ToString())
End Try
End If
End Sub
The deal is that controls have to be updated on the thread they were created on. It sounds like the AddText() routine is being called in the context of your async socket's thread. The AddText() routine will behave like a recursive function. The first time it's called, the InvokeRequired property will be true. This will cause it to be called again via the Invoke() call, which takes care of marshaling the data to the correct thread. The second time it's called, InvokeRequired will be false, and the control will be updated.
Fixed. I couldn't use Form1 to call the functions, because it's a type, its like a new var there with its own memory, since its a diff thread. So when I checked InvokeRequired, it said false because that Form1 belongs to that Thread, and thus no text was being displayed because I didn't even see the form. So just made a global var such as Public myForm As Form1 and assigned myForm to Form1 in Form1_Load.