473,387 Members | 1,611 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

One Thread Updates a Structure Field, But Another Thread Does Not See the Update

In my class which contains the code for my worker thread I have ...

Public MustInherit Class Base_Miner

#Region " Delegates for accessing main UI form "
Delegate Sub DelegAddProgressBar(ByVal uiform As Form1, ByRef si As
MTCC02.Form1.SiteRunOpts, _
ByVal numitems As Integer)
#End Region

Public globalinf As MTCC02.Form1.GlobalRunOpts
Public siteinf As MTCC02.Form1.SiteRunOpts
....

The constructor for this class does ...

Public Sub New(ByVal url As String, ByVal globalinfo As
MTCC02.Form1.GlobalRunOpts, _
ByRef siteinfo As MTCC02.Form1.SiteRunOpts)

....

globalinf = globalinfo 'save for LoadTextFile sub
siteinf = siteinfo 'save for LoadTextFile sub

It's the siteinf structure which I think is central to the problem I am
looking for some help with. What I think I am doing here is making the
structure available to all the methods of the Base_Miner class and all
classes which inherit from it. Right?

Still in the constuctor I do ...

Dim AddProgBar As DelegAddProgressBar = New DelegAddProgressBar(AddressOf
MTCC02.Form1.AddProgressBar)

globalinf.UIFormInst.Invoke(AddProgBar, New Object() {globalinf.UIFormInst,
siteinfo, NextDetailUrlsIndex})
Here in the constructor I think that I can use siteinf and siteinfo
interchangebly. Right?

On return from the Invoke the debugger shows that the "progbarProgress"
field of both siteinf and siteinfo is Nothing. ?!?!?

In my Form1 class, and this code is runs on my main/UI thread, I have ...

Public Shared Sub AddProgressBar(ByVal uiform As Form1, ByRef si As
SiteRunOpts, ByVal numitems As Integer)
si.progbarProgress = New ProgressBar
With si.progbarProgress
.Width = numitems \ 2
.Maximum = numitems
.Location = New Point(progbarProgress_xloc, si.yloc)
.Step = 1
End With
uiform.Controls.Add(si.progbarProgress)
End Sub 'AddProgressBar

At the end of this Sub, when I use the debugger and check the si argument,
the "progbarProgress" field is not Nothing and looks reasonable (to me!,
which is maybe not saying much). Also,the progressbar does get created - I
see it appear on the UI form. But back in the worker thread which is
running the Base_Miner code and which issued the Invoke which caused the
AddProgressBar code to be run the SiteRunOpts structure has Nothing in the
progbarProgress field.

What's going on here? Did the worker thread get its own copy of the
SiteRunOpts structure it was passed? How do I fix this?

Incidentally, does it matter is a structure is passed ByRef or ByVal so long
as you are only accessing fields within the structure? I think I've been
told it does not but earlier when I was passing the SiteRunOpts argument
ByVal I was wondering about that.

This has got me most frustrated, so I will be most grateful for any help.
Bob

Nov 10 '07 #1
4 1698
On Nov 10, 11:37 am, "eBob.com" <eBob....@totallybogus.comwrote:
In my class which contains the code for my worker thread I have ...

Public MustInherit Class Base_Miner

#Region " Delegates for accessing main UI form "
Delegate Sub DelegAddProgressBar(ByVal uiform As Form1, ByRef si As
MTCC02.Form1.SiteRunOpts, _
ByVal numitems As Integer)
#End Region

Public globalinf As MTCC02.Form1.GlobalRunOpts
Public siteinf As MTCC02.Form1.SiteRunOpts
...

The constructor for this class does ...

Public Sub New(ByVal url As String, ByVal globalinfo As
MTCC02.Form1.GlobalRunOpts, _
ByRef siteinfo As MTCC02.Form1.SiteRunOpts)

...

globalinf = globalinfo 'save for LoadTextFile sub
siteinf = siteinfo 'save for LoadTextFile sub

It's the siteinf structure which I think is central to the problem I am
looking for some help with. What I think I am doing here is making the
structure available to all the methods of the Base_Miner class and all
classes which inherit from it. Right?

Still in the constuctor I do ...

Dim AddProgBar As DelegAddProgressBar = New DelegAddProgressBar(AddressOf
MTCC02.Form1.AddProgressBar)

globalinf.UIFormInst.Invoke(AddProgBar, New Object() {globalinf.UIFormInst,
siteinfo, NextDetailUrlsIndex})

Here in the constructor I think that I can use siteinf and siteinfo
interchangebly. Right?

On return from the Invoke the debugger shows that the "progbarProgress"
field of both siteinf and siteinfo is Nothing. ?!?!?

In my Form1 class, and this code is runs on my main/UI thread, I have ...

Public Shared Sub AddProgressBar(ByVal uiform As Form1, ByRef si As
SiteRunOpts, ByVal numitems As Integer)
si.progbarProgress = New ProgressBar
With si.progbarProgress
.Width = numitems \ 2
.Maximum = numitems
.Location = New Point(progbarProgress_xloc, si.yloc)
.Step = 1
End With
uiform.Controls.Add(si.progbarProgress)
End Sub 'AddProgressBar

At the end of this Sub, when I use the debugger and check the si argument,
the "progbarProgress" field is not Nothing and looks reasonable (to me!,
which is maybe not saying much). Also,the progressbar does get created - I
see it appear on the UI form. But back in the worker thread which is
running the Base_Miner code and which issued the Invoke which caused the
AddProgressBar code to be run the SiteRunOpts structure has Nothing in the
progbarProgress field.

What's going on here? Did the worker thread get its own copy of the
SiteRunOpts structure it was passed? How do I fix this?

Incidentally, does it matter is a structure is passed ByRef or ByVal so long
as you are only accessing fields within the structure? I think I've been
told it does not but earlier when I was passing the SiteRunOpts argument
ByVal I was wondering about that.

This has got me most frustrated, so I will be most grateful for any help.
Bob
Sorry - I'm having a hard time following your post. As I understand
it, you are modifiying a structure on one thread and not seeing the
change on the other? Are you sure that they both are modifying the
same copy? Your question about ByVal vs. ByRef indicates that you have
a incomplete understanding of reference types vs. value types...
Which can definately lead to these kind of issues.

So, to quickly answer the question - yes, it most definately matters.

The long answer is why it matters.... A structure in VB.NET is an
object that inherits from system.valuetype. A class is an object that
inherits form system.reference type. What does that mean? It means
that like an Integer, a Byte, or any of the other numeric types, a
structures memory is allocated on the stack, not the heap. When a
structre is passed between methods, a byval call will cause a new copy
of the structure to be created. What that means is that any changes
made in the called procedure will not be propegated to the caller.
When a byref call is made, the address of the structure is passed - so
any changes made by the called procedure are propegated to the caller
because they are working on the same instance. This is with a value
type...

For instance:

Public Sub Main ()
Dim i As Integer = 10

Console.WriteLine ("i Before Call ByVal = {0}", i)
CallByValue (i)
Console.WriteLine ("i After Call ByVal = {0}", i)

Console.WriteLine ("i Before Call ByRef = {0}", i)
CallByRef (i)
Console.WriteLine ("i After Call ByRef = {0}", i)

End Sub

Private Sub CallByValue (ByVal i As Integer)
i = 100
End Sub

Private Sub CallByRef (ByRef i As Integer)
i = 100
End Sub

-- Output --
i Before Call ByVal = 10
i After Call ByVal = 10
i Before Call ByRef = 10
i After Call ByRef = 100

Where it becomes confusing somewhat is that this has the appearance of
being inconsitant with what happens with classes (reference types).
Because when they are passed byval, you can change properties on a the
object, and the changes are propegated to the caller... But, if you
realize that what is really being passed byval with a reference type
is actually the address of the object this will make sense. Reference
types are allocated dynamically on the heap, so what is actually
stored in an object variable is the memory location of the object.
What that means is that though you can change the state of the object
- you can not change the object reference...

That means in the called sub, if the object is passed by value, that
if you do:

theObjectParam = new MyObject()

The caller will not see the new object when the call returns. They
will still have their old refernce unchanged. Now, if they had passed
the object byref, their refrence would now point to the new
instance :)

Anyway, you might want to post a more complete example of your
problem (try to keep at small as possible). It would make it much
easier to spot any issues.

--
Tom Shelton

Nov 10 '07 #2
"eBob.com" <eB******@totallybogus.comwrote in
news:#U**************@TK2MSFTNGP06.phx.gbl:
Incidentally, does it matter is a structure is passed ByRef or ByVal
so long as you are only accessing fields within the structure? I
think I've been told it does not but earlier when I was passing the
SiteRunOpts argument ByVal I was wondering about that.
Yes it does - structures are value types which means if you pass ByVal, the
structure will be duplicated and you'll have 2 copies of the data.

Regular objects are reference type objects - in which case passing
ByRef/ByVal is a moot point.
Nov 10 '07 #3
On Nov 10, 4:26 pm, Spam Catcher <spamhoney...@rogers.comwrote:
"eBob.com" <eBob....@totallybogus.comwrote innews:#U**************@TK2MSFTNGP06.phx.gbl:
Incidentally, does it matter is a structure is passed ByRef or ByVal
so long as you are only accessing fields within the structure? I
<snip>
>
Regular objects are reference type objects - in which case passing
ByRef/ByVal is a moot point.
Not to argue... But, it's not exactly a moot point. It really depends
on what the method does. Now, normally I wouldn't do this - but, if
your method is intended to initialize the object reference then you
need to pass it ByRef.

Still, in most scenarios, then it really makes no difference.

--
Tom Shelton

Nov 10 '07 #4

"Tom Shelton" <to*********@comcast.netwrote in message
news:11*********************@19g2000hsx.googlegrou ps.com...
On Nov 10, 11:37 am, "eBob.com" <eBob....@totallybogus.comwrote:
>In my class which contains the code for my worker thread I have ...

Public MustInherit Class Base_Miner

#Region " Delegates for accessing main UI form "
Delegate Sub DelegAddProgressBar(ByVal uiform As Form1, ByRef si As
MTCC02.Form1.SiteRunOpts, _
ByVal numitems As Integer)
#End Region

Public globalinf As MTCC02.Form1.GlobalRunOpts
Public siteinf As MTCC02.Form1.SiteRunOpts
...

The constructor for this class does ...

Public Sub New(ByVal url As String, ByVal globalinfo As
MTCC02.Form1.GlobalRunOpts, _
ByRef siteinfo As MTCC02.Form1.SiteRunOpts)

...

globalinf = globalinfo 'save for LoadTextFile sub
siteinf = siteinfo 'save for LoadTextFile sub

It's the siteinf structure which I think is central to the problem I am
looking for some help with. What I think I am doing here is making the
structure available to all the methods of the Base_Miner class and all
classes which inherit from it. Right?

Still in the constuctor I do ...

Dim AddProgBar As DelegAddProgressBar = New DelegAddProgressBar(AddressOf
MTCC02.Form1.AddProgressBar)

globalinf.UIFormInst.Invoke(AddProgBar, New Object()
{globalinf.UIFormInst,
siteinfo, NextDetailUrlsIndex})

Here in the constructor I think that I can use siteinf and siteinfo
interchangebly. Right?

On return from the Invoke the debugger shows that the "progbarProgress"
field of both siteinf and siteinfo is Nothing. ?!?!?

In my Form1 class, and this code is runs on my main/UI thread, I have ...

Public Shared Sub AddProgressBar(ByVal uiform As Form1, ByRef si As
SiteRunOpts, ByVal numitems As Integer)
si.progbarProgress = New ProgressBar
With si.progbarProgress
.Width = numitems \ 2
.Maximum = numitems
.Location = New Point(progbarProgress_xloc, si.yloc)
.Step = 1
End With
uiform.Controls.Add(si.progbarProgress)
End Sub 'AddProgressBar

At the end of this Sub, when I use the debugger and check the si
argument,
the "progbarProgress" field is not Nothing and looks reasonable (to me!,
which is maybe not saying much). Also,the progressbar does get created -
I
see it appear on the UI form. But back in the worker thread which is
running the Base_Miner code and which issued the Invoke which caused the
AddProgressBar code to be run the SiteRunOpts structure has Nothing in
the
progbarProgress field.

What's going on here? Did the worker thread get its own copy of the
SiteRunOpts structure it was passed? How do I fix this?

Incidentally, does it matter is a structure is passed ByRef or ByVal so
long
as you are only accessing fields within the structure? I think I've been
told it does not but earlier when I was passing the SiteRunOpts argument
ByVal I was wondering about that.

This has got me most frustrated, so I will be most grateful for any help.
Bob

Sorry - I'm having a hard time following your post. As I understand
it, you are modifiying a structure on one thread and not seeing the
change on the other? Are you sure that they both are modifying the
same copy? Your question about ByVal vs. ByRef indicates that you have
a incomplete understanding of reference types vs. value types...
Which can definately lead to these kind of issues.

So, to quickly answer the question - yes, it most definately matters.

The long answer is why it matters.... A structure in VB.NET is an
object that inherits from system.valuetype. A class is an object that
inherits form system.reference type. What does that mean? It means
that like an Integer, a Byte, or any of the other numeric types, a
structures memory is allocated on the stack, not the heap. When a
structre is passed between methods, a byval call will cause a new copy
of the structure to be created. What that means is that any changes
made in the called procedure will not be propegated to the caller.
When a byref call is made, the address of the structure is passed - so
any changes made by the called procedure are propegated to the caller
because they are working on the same instance. This is with a value
type...

For instance:

Public Sub Main ()
Dim i As Integer = 10

Console.WriteLine ("i Before Call ByVal = {0}", i)
CallByValue (i)
Console.WriteLine ("i After Call ByVal = {0}", i)

Console.WriteLine ("i Before Call ByRef = {0}", i)
CallByRef (i)
Console.WriteLine ("i After Call ByRef = {0}", i)

End Sub

Private Sub CallByValue (ByVal i As Integer)
i = 100
End Sub

Private Sub CallByRef (ByRef i As Integer)
i = 100
End Sub

-- Output --
i Before Call ByVal = 10
i After Call ByVal = 10
i Before Call ByRef = 10
i After Call ByRef = 100

Where it becomes confusing somewhat is that this has the appearance of
being inconsitant with what happens with classes (reference types).
Because when they are passed byval, you can change properties on a the
object, and the changes are propegated to the caller... But, if you
realize that what is really being passed byval with a reference type
is actually the address of the object this will make sense. Reference
types are allocated dynamically on the heap, so what is actually
stored in an object variable is the memory location of the object.
What that means is that though you can change the state of the object
- you can not change the object reference...

That means in the called sub, if the object is passed by value, that
if you do:

theObjectParam = new MyObject()

The caller will not see the new object when the call returns. They
will still have their old refernce unchanged. Now, if they had passed
the object byref, their refrence would now point to the new
instance :)

Anyway, you might want to post a more complete example of your
problem (try to keep at small as possible). It would make it much
easier to spot any issues.

--
Tom Shelton
Hi Tom, Thanks so much for your prompt response. I had indeed forgotten
that structures are value types. But I don't think that (should have!) had
anything to do with my problem. Long story short ... the multi-threading
was a red herring. I changed to a single thread and the problem persisted.
Then I changed the structure to a class and bingo! that fixed the problem.
Then I went back to multi-threading and all was still well. What continues
to confuse me is why fields in a structure passed ByRef should behave any
different from fields in a class passed ByRef. That appears to be what was
happening. (The caller sees a change to a field when it is in a class but
not when it is in a structure, both passed ByRef.) I will try to come up
with a complete but really simple example of what I was experiencing and
post it. Thanks again, Bob
Nov 12 '07 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: Gary | last post by:
I haver a table of students - Say 100 students that I need to be able to update/delete and amend. I know I can do this one student at a time which is simple but lets say I want to see all the...
9
by: Jervin Justin | last post by:
Hi, I've been having this problem for some time with Web Forms: I have a web app that sends data to a service when the user presses a button. Based on the data, the server will send several...
4
by: Charles Law | last post by:
Hi guys. I have two threads: a main thread and a background thread. Lots of stuff happens in the background thread that means I have to update several (lots) of controls on a form. It is...
3
by: Tlink | last post by:
I have a master control program that needs to run continuously, accepting data and updating a datagrid for the user. As a result I have setup 2 threads, one accepts and processes incoming requests...
14
by: joey.powell | last post by:
I am using VS2005 for a windows forms application. I need to be able to use a worker thread function to offload some processing from the UI thread. The worker thread will need access to a...
3
by: =?ISO-8859-1?Q?Gregory_Pi=F1ero?= | last post by:
Hi Python Experts, I hope I can explain this right. I'll try. Background: I have a module that I leave running in a server role. It has a module which has data in it that can change. So...
5
by: temp2 | last post by:
Hello, I have an app that reads data params from a stream and updates controls accordingly. The stream reader is on a different thread than the main thread that created the controls. I fully...
7
by: Sin Jeong-hun | last post by:
I've using thread a lot in C#, but all of them were just single method with no return value or paramenters. It may sound bizarre but, can't it be a class? I'm writing an Windows application that...
8
by: Brad Walton | last post by:
Hello. First post, but been doing a bit of reading here. I am working on a project in Java, but decided to switch over to C# after seeing some of the additional features I can get from C#. One of...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.