|
Stack<Items> stack ...;
public void MyThread(object whocares){
while(go){
Item item = null;
lock(stack){
item = stack.Pop();
}
if(item != null){
}
}
}
Then you need somewhere to run start the loop
System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(MyThread));
Now just push items on the stack when they need to be called in another thread. There are many modifications to this basic theme.
Need software developed? Offering C# development all over the United States, ERL GLOBAL, Inc is the only call you will have to make.
If you don't ask questions the answers won't stand in your way.
Most of this sig is for Google, not ego.
|
|
|
|
|
Thanks Ennis,
I have some confusion about your soluton. I think the reason of why you use stack is because there are some shared object instances between the threads, correct? But in my situation, there is no shared items between my thread jobs. You can read my code again for my thread job in method "ThreadJob".
Any comments? Please feel free to correct me if I am wrong.
regards,
George
|
|
|
|
|
Maybe a single task is not taking enough time to be worth creating a thread for? If that's the case, try to use the ThreadPool and see if that works better. You don't have to use it "explicitly", creating a delegate and calling BeginInvoke on it should be fine. If you want to wait for all tasks to finish, you could store the IAsyncResults in an array and later call EndInvoke on all of them.
edit: lol @ my stupid typo Last modified: 42mins after originally posted --
|
|
|
|
|
|
Ok, this may not make much of a difference (if any), but you could use some elements like:
(this is not code - just some 'useful' elements)
delegate void ThreadJobDelegate(int index);
IAsyncResult[] results = new IAsyncResult[number];
ThreadJobDelegate th = new ThreadJobDelegate(ThreadJob);
results[index] = th.BeginInvoke(index, null, null);
foreach(IAsyncResult res) th.EndInvoke(res);
I would also time each call to ThreadJob, it doesn't have to be fancy, just to get an idea of how long each call is taking - and time the total (from before the first BeginInvoke till after the last EndInvoke), to see whether threading improved it at all (and if so, by how much).
|
|
|
|
|
Thanks harold!
I have applied your ideas but performance never improves. Here is my code modified according to your idea. Any ideas? Or anything wrong with my code?
class Program
{
static Service1[] clients = null;
static IAsyncResult[] results = null;
static AsyncMethodCaller[] callers = null;
public delegate void AsyncMethodCaller(object index);
static void ThreadJob (object index)
{
for (int i = 0; i < 100; i++)
{
clients[(int)index].HelloWorld();
}
}
static void Main(string[] args)
{
Console.WriteLine("Specify number of threads: ");
int number = Int32.Parse(Console.ReadLine());
clients = new Service1[number];
results = new IAsyncResult[number];
callers = new AsyncMethodCaller[number];
for (int i = 0; i < number; i++)
{
clients[i] = new Service1();
clients[i].EnableDecompression = true;
callers[i] = new AsyncMethodCaller(ThreadJob);
results[i] = callers[i].BeginInvoke(i, null, null);
}
DateTime begin = DateTime.Now;
int j = 0;
foreach (IAsyncResult res in results)
{
callers[j].EndInvoke(res);
j++;
}
Console.WriteLine("Total elapsed time (s): " + (DateTime.Now - begin).TotalSeconds);
Console.ReadLine();
return;
}
}
regards,
George
|
|
|
|
|
Ok that would explain it then I suppose..
It should be possible to use on 1 new AsyncMethodCaller - but I seriously doubt it would have a impact on the performance.
If performance can not be improved with threading, then it will just have to be improved in some other way..
|
|
|
|
|
Thanks harold!
"It should be possible to use on 1 new AsyncMethodCaller - but I seriously doubt it would have a impact on the performance." -- how could we use only one AsyncMethodCaller instance? Could you show me some simple pseudo code based on my code please?
regards,
George
|
|
|
|
|
Like so:
class Program
{
static Service1[] clients = null;
public delegate void AsyncMethodCaller(int index);
static void ThreadJob (int index)
{
for (int i = 0; i < 100; i++)
{
clients[index].HelloWorld();
}
}
static void Main(string[] args)
{
Console.WriteLine("Specify number of threads: ");
int number = Int32.Parse(Console.ReadLine());
clients = new Service1[number];
IAsyncResult[] results = new IAsyncResult[number];
AsyncMethodCaller TJ = new AsyncMethodCaller(ThreadJob)
for (int i = 0; i < number; i++)
{
clients[i] = new Service1();
clients[i].EnableDecompression = true;
results[i] = TJ.BeginInvoke(i, null, null);
}
DateTime begin = DateTime.Now;
foreach (IAsyncResult res in results)
TJ.EndInvoke(res);
Console.WriteLine("Total elapsed time (s): " + (DateTime.Now - begin).TotalSeconds);
Console.ReadLine();
return;
}
}
|
|
|
|
|
Thanks harold,
I have tried but no performance improvements. Do you have any other ideas to improve performance? I find CPU/memory/network are used a little part, so I think there is room to improve performance.
regards,
George
|
|
|
|
|
Very strange.. I'm really out of ideas now..
There is just 1 explanation I can think of - the web server is handling all requests sequentially and non-pipelined.
|
|
|
|
|
Thanks harold,
Two more questions,
1.
My code is posted and simple. Could you reproduce my issue? I am not suspecting it is my environment issue.
2.
"the web server is handling all requests sequentially and non-pipelined" -- do you have any ways or documents to prove it?
regards,
George
|
|
|
|
|
1. no, I would have to know what HelloWorld() does, and how it does it, and probably a lot more
2. well, if it weren't, threading would cause a speed-up. And it didn't.
|
|
|
|
|
Thanks harold,
For 1,
Here is my code at server side. Could you reproduce my problem?
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public double HelloWorld()
{
return new Random().NextDouble();
}
}
For 2,
I could understand your points. But do you have any documents to prove? I think if web service could only serve requests sequentially other than simualtenaously, it is so bad and degrade performance design. I can not believe it is designed in this way.
regards,
George
|
|
|
|
|
1) Alright it looks like it should be doing it sequentially, otherwise Random.NextDouble could fail, no method in System.Random is threadsafe.
But it should barely take any time at all.
2) Documents... well. Take Amdahl's_law for example, in which P is the proportion of the program that has been made parallel. P would be zero, so you'd get the limit 1 / (1 - 0 + 0/n) where n goes to infinity. So as you can see, the answer is 1, independent of n, meaning: no benefit at all. But of course we knew that that already, since we made no improvement.
3?) I see no good reason for this to be slow, it should be blazingly fast - it's only generating a bunch of random numbers and sending them over right?
|
|
|
|
|
Thanks harold,
1.
"otherwise Random.NextDouble could fail, no method in System.Random is threadsafe." -- I agree it is not thread safe, but I disagree since it is not thread safe, web service will do sequentially. Since each time I creat a new instance of Random object. You can check my code. Any comments?
2.
"Alright it looks like it should be doing it sequentially" -- how do you prove it? My current confusion is, web service has to do sequentially or could do in parallel?
regards,
George
|
|
|
|
|
1) doh yes, sorry, I just woke up
2) you can easily prove it informally by measuring the difference between doing some simultaneous calls vs some sequential calls - if there is no difference (or if the parallel calls took longer) than there are only 2 possible cases:
1: the simultaneous calls were handled sequentially.
2: the simultaneous calls were so short that the overhead of doing them simultaneously was as big as or bigger than the benefit.
You can, of course, test which case it is. Just make the method that is called a good bit longer (say, generate 10k random numbers, then return the last one). If it benefits from threading then it was case 2, otherwise case 1.
|
|
|
|
|
Thanks harold,
1.
I did the following test and I think the web service should work simultaneously.
Here is my new code at server side, and I add an additional Sleep.
I think if working sequentially, it will take 5 * 1000 seconds to complete all jobs (10 threads and each thread get 100 random number), but in my testing experience, it takes about 55 seconds.
Does it prove web service works simultaneously? Any comments?
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public double HelloWorld()
{
Thread.Sleep(500);
return new Random().NextDouble();
}
}
2.
Could you reproduce my issue? I want to know whether it is my environment issue if you could not reproduce it.
3.
If you could reproduce, any ideas to improve performance?
regards,
George
|
|
|
|
|
1) it would take 1000 * 500 miliseconds = 500 seconds if it were sequentially. Which is more than 55 seconds, so, by RAA, it is proven that it wasn't purely sequentially.
Now that's a real breakthrough - it means the threading works but the task (without the sleep) is too short.
2) well, not directly. But it works like that without webservers being involved as well.
3) The threading will help when you let the web method do something useful.
|
|
|
|
|
Thanks harold,
1.
"well, not directly. But it works like that without webservers being involved as well." -- confused. Especially what do you mean "without webservers being involved"? There is web server, since I run it as web service and IIS hosts it.
2.
"The threading will help when you let the web method do something useful." -- confused about what you mean. Could you describe something more?
regards,
George
|
|
|
|
|
1 just means that I tested without using a webserver
2 means that new Random().NextDouble() does not take enough time to be worth multithreading it in this case
|
|
|
|
|
My understanding is that a web service has only one process at a time, so all requests have to queue up anyway.
|
|
|
|
|
Thanks PIEBALDconsult!
1.
"web service has only one process at a time" -- at client side or server side, do you mean?
2.
"web service has only one process at a time" -- any documents to prove your points? I am very interested to learn from it.
regards,
George
|
|
|
|
|
1. Server side, the service doesn't run on the client.
2. If I did, I would have given a more authoritative answer.
|
|
|
|
|
Thanks PIEBALDconsult!
If the bottleneck is "web service has only one process at a time", how do you prove it or show some related documents?
regards,
George
|
|
|
|