Windows Vista Forums
Vista Forums Home Join Vista Forums Windows 7 Forum Vista Tutorials Tags
Welcome to Windows Vista Forums. Our forum is dedicated to helping you find solutions with any problems, errors or issues you are experiencing with Windows Vista. The Vista forum also covers news and updates and has an extensive Windows Vista tutorial section that covers a wide range of tips and tricks.

Go Back   Vista Forums > Misc Newsgroups > .NET General

Vista - I want to thread heavily

Reply
 
Old 05-28-2008   #1 (permalink)
jp2msft


 
 

I want to thread heavily

I am developing a new application.

Since it is being developed from scratch, I want to implement a lot of
threading - especially for my SQL calls.

The problem I noticed is that I can't seem to interact with data that is in
a thread, and all data that goes to a thread must be static - hence my
application can not access it.

Is there a place that spells out how to thread my routines and make it so
that I can pass data to it and read the resulting data that results?

My preferred language is C# or VB, using Visual Studio 2005.

Thanks for the help!

My System SpecsSystem Spec
Old 05-28-2008   #2 (permalink)
Jeroen Mostert


 
 

Re: I want to thread heavily

jp2msft wrote:
Quote:

> I am developing a new application.
>
> Since it is being developed from scratch, I want to implement a lot of
> threading - especially for my SQL calls.
>
Threading is not some sort of fairy dust that will make your application
good if you sprinkle lots of it. Threading is never a goal, it's a means, so
starting out with the idea that you want to have "a lot of threading" is
broken to begin with. What you want is the least threading that still meets
your goals, because threading adds complexity.

In particular, if your calls all go to the same database, threading is
unlikely to be of much help, because the database will only have a limited
capacity for processing your requests in parallel. Your average server will
of course have tremendous parallel capacity, but a) you'll have to share it
with everyone else and b) your requests will probably get through *faster*
if you execute them one by one rather than forcing the DB to do them in
parallel.

That's not to say executing DB requests in parallel in a single application
never has any merit, but if your goal is just to increase throughput, it's
probably sufficient to use a limited number (possibly just one) of
asynchronous calls (.BeginExecuteReader() and the like) and leave the rest
to the thread pool.

If you just want to ensure your UI remains response as you're processing
data, using asynchronous calls, BackgroundWorker and/or
ThreadPool.QueueUserWorkItem() should do the trick.
Quote:

> The problem I noticed is that I can't seem to interact with data that is in
> a thread, and all data that goes to a thread must be static - hence my
> application can not access it.
>
Where do you get this idea? A thread can access any data that's reachable to
it, and you can start one from any object.

A thread routine is a delegate that has full access to the members of its
declaring class, and on top of that, Thread.Start() and all the asynchronous
method allow you to pass an arbitrary object "state" to store whatever
additional data you require. So:

class A {
int a;

void foo() {
string extraData;
Thread thread = new Thread(threadMethod, extraData);
thread.Start();
}

void threadMethod(object state) {
string extraData = (string) state;
// "a" is accessible here too
}

void bar(SqlCommand c) {
string extraData;
c.BeginExecuteReader(endExecuteReader, c);
}

void endExecuteReader(IAsyncResult ar) {
SqlCommand c = (SqlCommand) ar.AsyncState;
// "a" is accessible here too
using (SqlDataReader r = c.EndExecuteReader(ar)) {
...
}
}
}
Quote:

> Is there a place that spells out how to thread my routines and make it so
> that I can pass data to it and read the resulting data that results?
>
Try googling "asynchronous programming". It's the least bothersome way of
leveraging parallel processing.

--
J.
http://symbolsprose.blogspot.com
My System SpecsSystem Spec
Old 05-28-2008   #3 (permalink)
jp2msft


 
 

Re: I want to thread heavily

Thanks Mr. Mostert.

My goal is to keep the UI responsive. Sometimes our connections are broken
in this manufacturing environment, and this causes the App to hang until the
server request times out.

I'll look into the background worker threads.

ThreadPool.QueueUserWorkItem() is something I've never heard of.

"Jeroen Mostert" wrote:
Quote:

> If you just want to ensure your UI remains response as you're processing
> data, using asynchronous calls, BackgroundWorker and/or
> ThreadPool.QueueUserWorkItem() should do the trick.
>
> Try googling "asynchronous programming". It's the least bothersome way of
> leveraging parallel processing.
>
> --
> J.
> http://symbolsprose.blogspot.com
>
My System SpecsSystem Spec
Old 05-28-2008   #4 (permalink)
Jeroen Mostert


 
 

Re: I want to thread heavily

jp2msft wrote:
Quote:

> Thanks Mr. Mostert.
>
Please, either "Jeroen" or "whatsyerface" will do fine.
Quote:

> My goal is to keep the UI responsive. Sometimes our connections are broken
> in this manufacturing environment, and this causes the App to hang until the
> server request times out.
>
BackgroundWorker should be good for this, as it was designed for UI
scenarios. In fact, the documentation mentions your very scenario:

"The BackgroundWorker class allows you to run an operation on a separate,
dedicated thread. Time-consuming operations like downloads and database
transactions can cause your user interface (UI) to seem as though it has
stopped responding while they are running. When you want a responsive UI and
you are faced with long delays associated with such operations, the
BackgroundWorker class provides a convenient solution."
Quote:

> ThreadPool.QueueUserWorkItem() is something I've never heard of.
>
It's quite useful, but also quite specialized -- it's a "fire and forget"
way of doing something in the background, and the threadpool will ensure
these tasks will run with optimal parallelism for the system.

Unfortunately, the "forget" part means you have to implement synchronization
yourself if you want to know if/when the work was done. For most scenarios
asynchronous calls are more appropriate, and for applications with a UI
BackgroundWorker can do the heavy lifting, since it was designed with
progress reporting in mind.

--
J.
http://symbolsprose.blogspot.com
My System SpecsSystem Spec
Old 05-29-2008   #5 (permalink)
jp2msft


 
 

Re: I want to thread heavily

Jeroen,

I've found a very through example on the BackgroundWorker Class in the VS
Help, but I have a question that it does not address.

I have at least three (3) different, time-consuming tasks that I'd like to
use the BackgroundWorker Class on. Two are for database queries, and one is
for text validation.

My question is: Can the one BackgroundWorker Class be used for all three (3)
of these tasks? Some of the tasks do, on occasion, call one of the other
tasks.

I see in the BackgroundWorker_DoWork method that there is a "sender" object.
Would the "sender" be the name of the function that I used to call the
BackgroundWorker's RunWorkerAsync method?

Or, should I drop a separate BackgroundWorker component on the form for each
of my time-consuming tasks?

Did this question make sense?
My System SpecsSystem Spec
Old 05-29-2008   #6 (permalink)
Jeroen Mostert


 
 

Re: I want to thread heavily

jp2msft wrote:
Quote:

> I've found a very through example on the BackgroundWorker Class in the VS
> Help, but I have a question that it does not address.
>
> I have at least three (3) different, time-consuming tasks that I'd like to
> use the BackgroundWorker Class on. Two are for database queries, and one is
> for text validation.
>
> My question is: Can the one BackgroundWorker Class be used for all three (3)
> of these tasks? Some of the tasks do, on occasion, call one of the other
> tasks.
>
If you're already running a task in the background, then there's no point to
having that task start its dependent task in the background separately. I'll
demonstrate what I mean shortly.
Quote:

> I see in the BackgroundWorker_DoWork method that there is a "sender" object.
> Would the "sender" be the name of the function that I used to call the
> BackgroundWorker's RunWorkerAsync method?
>
No, "sender" in an event handler is always the object that triggered the
event. You can have multiple BackgroundWorkers share the same event handler,
and "sender" would contain the BackgroundWorker that the event is actually
for. Let's put this aside for a minute.

What you could do is create your own methods that perform whatever
long-running task you need, possibly returning data. Let's say you have this:

DataTable getLotsOfData() { ... }
ValidationResults validateLotsOfText(string lotsOfText) { ... }

Now, when you need to perform one of these tasks from your UI thread, you
can call on a BackgroundWorker. You can create these programmatically or
drag them as components. Let's say you use components, as it's a little
easier. You can do it all in one BackgroundWorker, but this is harder to
program -- it's easier to use separate BackgroundWorkers for separate tasks.
(If you have lots of different tasks that need to run this way, or more than
one instance of the same task, you should create BackgroundWorkers from your
code rather than using design-time components.)

So let's say you have two BackgroundWorker components, one for LotsOfData
and the other for LotsOfText. When you need to start either of these
activities from your UI, you call .RunWorkerAsync() on the appropriate
BackgroundWorker:

GetLotsOfDataBackgroundWorker.RunWorkerAsync();
ValidateLotsOfTextWorker.RunWorkerAsync(lotsOfText);

The event handler for ValidateLotsOfTextWorker might look like this, calling
your method:

private void ValidateLotsOfTextWorker_DoWork(object sender,
DoWorkEventArgs e) {
string lotsOfText = (string) e.Argument;
e.Result = validateLotsOfText(lotsOfText)
}

When this is done, the worker's RunWorkerCompleted event will fire:

private void ValidateLotsOfTextWorker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e) {
if (e.Error != null) {
// Handle the error
} else {
ValidationResults v = (ValidationResults) e.Result;
// do something with the results
}
}

Now let's say you do the same for LotsOfData, but LotsOfData needs to
validate LotsOfText as part of its operation. Simply call that method
directly from within the DoWork handler:

private void GetLotsOfDataBackgroundWorker_DoWork(object sender,
DoWorkEventArgs e) {
// go to the database and get LotsOfText here
ValidationResults v = validateLotsOfText(lotsOfText);
}

When you want a long-running task done from your UI, use the
BackgroundWorker. If you're already in the background, you don't need to
bother with that and you can simply call methods as you're used to. There's
no need for the *background* task to be responsive, after all.

There's one thing that won't work very well if you do it like this, and
that's progress reporting. If you want your long-running task to report
progress, things get more complicated because you'll want your methods to
call on a BackgroundWorker to do that. But you can't call on just any
BackgroundWorker, because your UI thread might be using it -- you need to
pass the BackgroundWorker to the dependent method. Once you've reached this
point it's probably easier to create BackgroundWorker instances yourself and
not use components. If you don't need to report progress, the above method
will do fine.

--
J.
http://symbolsprose.blogspot.com
My System SpecsSystem Spec
Reply

Thread Tools


Similar Threads
Thread Forum
How do the current thread get thread notification of OS intruption .NET General
Start a new thread from an existing thread, which was started from atimer .NET General
thread General Discussion
Battery continues to drain heavily after my IBM X 61s has hibernated Vista General
Where is my thread? Vista music pictures video


Vista Forums is an independent web site and has not been authorized,
sponsored, or otherwise approved by Microsoft Corporation.
"Windows Vista", the Start Orb, and related materials are trademarks of Microsoft Corp.
© Designer Media Ltd

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46