WebClient OpenRead & Threading Issue

  • Thread starter Thread starter JS
  • Start date Start date
J

JS

All,

I have been working on a windows service that with retrieve XML files
from remote sites at a predetermined frequency. I am using the
WebClient class to retrieve any XML files located on web servers. When
I execute a call to each remote source in linear progression I
encounter no problems. If I execute the service with only one remote
source identified I encounter no problems. It is only when I try to
execute the service with multiple sources identified that I encounter
the problem.

After the threading was incorporated I started receiving the following
error:
"Non-negative number required.
Parameter name: byteCount"

"byteCount" is not a variable that I have declared and after a
combination of online research and a thorough application review I have
determined that this variable is part of the framework itself.

I have tried implementing synchronization using the Mutex class with no
success. I have also tried the various solutions (delegation, etc.)
identified in the newsgroups posted in response to similar issues to
the one I am encountering with no avail.

Could someone please provide me with some guidance on this issue? I
have spent more time than I would like on this issue and would like to
get past it before it costs me my sanity. I can provide a working
sample of the issue if required just let me know.

Thanks in advance.

JS.
 
JS said:
All,

I have been working on a windows service that with retrieve XML files
from remote sites at a predetermined frequency. I am using the
WebClient class to retrieve any XML files located on web servers.
When I execute a call to each remote source in linear progression I
encounter no problems. If I execute the service with only one remote
source identified I encounter no problems. It is only when I try to
execute the service with multiple sources identified that I encounter
the problem.

After the threading was incorporated I started receiving the following
error:
"Non-negative number required.
Parameter name: byteCount"

"byteCount" is not a variable that I have declared and after a
combination of online research and a thorough application review I
have determined that this variable is part of the framework itself.

I have tried implementing synchronization using the Mutex class with
no success. I have also tried the various solutions (delegation,
etc.) identified in the newsgroups posted in response to similar
issues to the one I am encountering with no avail.

Could someone please provide me with some guidance on this issue? I
have spent more time than I would like on this issue and would like to
get past it before it costs me my sanity. I can provide a working
sample of the issue if required just let me know.

Note that this class isn't thread-safe.

Are you reusing the same WebClient instance across threads?

It's much easier and more scalable to use one WebClient instance per
thread.

Cheers,
 
Note that this class isn't thread-safe.
Are you reusing the same WebClient instance across threads?

It's much easier and more scalable to use one WebClient instance per
thread.

Hi Joerg,

Thanks for the response. In reply to your question I am not using one
WebClient instance across threads. Originally I was but I corrected
that prior to receiving the error previously identified. Presently I
am using one instance per thread.

The class that the WebClient is within is self-contained and is
instantiated uniquely by the calling class. It is this calling class
that is created uniquely for each thread.

i.e.

[delegate class]
.....
thr = new Thread(new ThreadStart(AddressOf GenService.GetSourceInfo))

[inside GenService class]
....
dim oRemote as new Remote()

[inside Remote class]

private shared oWC as new WebClient
....
private function GetData() as boolean
....
dim sr as streamreader
....
sr = new StreamReader(oWC.OpenRead(URL))
....
end function

That is the line where it fails.

Does that make sense? I hope the clarification helps.

Regards,

J.
 
....
[delegate class]
....
thr = new Thread(new ThreadStart(AddressOf GenService.GetSourceInfo))

[inside GenService class]
...
dim oRemote as new Remote()

[inside Remote class]

private shared oWC as new WebClient
...
....
As far as I can see, WebClient is shared, which I guess is VB equivalent of
static in C#. That means that all instances of Remote class will use same
WebClient. Can you test with 'shared' keyword removed?

Regards,
Goran
 
JS said:
Note that this class isn't thread-safe.

Are you reusing the same WebClient instance across threads?

It's much easier and more scalable to use one WebClient instance per
thread.

Hi Joerg,

Thanks for the response. In reply to your question I am not using one
WebClient instance across threads. Originally I was but I corrected
that prior to receiving the error previously identified. Presently I
am using one instance per thread.

The class that the WebClient is within is self-contained and is
instantiated uniquely by the calling class. It is this calling class
that is created uniquely for each thread.

i.e.

[delegate class]
....
thr = new Thread(new ThreadStart(AddressOf GenService.GetSourceInfo))

[inside GenService class]
...
dim oRemote as new Remote()

[inside Remote class]

private shared oWC as new WebClient
...
private function GetData() as boolean
...
dim sr as streamreader
...
sr = new StreamReader(oWC.OpenRead(URL))
...
end function

That is the line where it fails.

Does that make sense? I hope the clarification helps.

Well, there's nothing much to say after Goran's post. You share a
single instance between threads. Use a WebClient instance per thread.

Cheers,
 
Hi Goran,

Yes, that is correct. "Shared' is the VB equivalent to static in C#.
I have declared this variable as such based on the .NET 1.1 SDK stating
that the only threadsafe members of this type are the public static
variables. However, I will make the change and see what happens.

[a short while later]
I have just tried changing how the WebClient reference is instantiated
to not use the "Shared" keyword and the error still occurs. I have
tried declaring the variable as both public and private to no avail.

Would you have any other suggestions?

Regards,

Jeff.
 
JS said:
Hi Goran,

Yes, that is correct. "Shared' is the VB equivalent to static in C#.
I have declared this variable as such based on the .NET 1.1 SDK
stating that the only threadsafe members of this type are the public
static variables. However, I will make the change and see what
happens.

[a short while later]
I have just tried changing how the WebClient reference is instantiated
to not use the "Shared" keyword and the error still occurs. I have
tried declaring the variable as both public and private to no avail.

Would you have any other suggestions?

Jeff,

*don't* use a WebClient object that is a class member (even if it is
non-static) when multiple threads may execute methods of a single
instance of your GenService class.

The easiest and safest thing to do is to create a WebClient object as a
local variable in your GetData() method and not to use instance fields.
Thus, each thread will have its own WebClient instance, and there will
be no threading issues.

Cheers,
 
Hi Goran/Joerg,

First and foremost thank you both for taking the time to patiently
explain what was going on and offer tips. About all I have to say
is....

$@#%$#$

This exercise will teach me to RTFM a little more closely. I realize
now when I read the information regarding Thread Safety in the SDK for
the WebClient class that I "skimmed" it rather than "read" it and did
not note the obvious....that the comments relate to the MEMBERS of the
class and not the class itself.

Thank you both again for the assistance.

Regards,

Jeff.
 
Back
Top