1

I have two questions:

  1. Is there a way to insert a ThreadPool functoin that dosen't gets object as parameter(to insert a function to threadPool it need to be function that return void and ged one parameter -object) e.g i want to insert this function: double foo(int a,double b,string c)?
  2. Is there a way to wait to thread in the pool (like join)?

5 Answers 5

5

For the first part, the easiest approach is probably:

Assuming a method per your description:

public double foo(int a, double b, string c) { ... } 

You can queue this on the thread pool with:

ThreadPool.QueueUserWorkItem(o => foo(a, b, c)); 

For the second part, while you can't wait on a ThreadPool thread, you can call methods asynchronously on the thread pool, and wait on their completion (which seems to be what you're looking for).

Again, assuming the Foo method is defined as above.

Define a Delegate for Foo:

private delegate double FooDelegate(int a, double b, string c); 

Then to call Foo asynchronously using the BeginInvoke/EndInvoke methods of the FooDelegate:

// Create a delegate to Foo FooDelegate fooDelegate = Foo; // Start executing Foo asynchronously with arguments a, b and c. var asyncResult = fooDelegate.BeginInvoke(a, b, c, null, null); // You can then wait on the completion of Foo using the AsyncWaitHandle property of asyncResult if (!asyncResult.CompletedSynchronously) { // Wait until Foo completes asyncResult.AsyncWaitHandle.WaitOne(); } // Finally, the return value can be retrieved using: var result = fooDelegate.EndInvoke(asyncResult); 

To address the question raised in the comments. If you want to execute multiple function calls in parallel and wait for them all to return before continuing, you could use:

// Create a delegate to Foo FooDelegate fooDelegate = Foo; var asyncResults = new List<IAsyncResult>(); // Start multiple calls to Foo() in parallel. The loop can be adjusted as required (while, for, foreach). while (...) { // Start executing Foo asynchronously with arguments a, b and c. // Collect the async results in a list for later asyncResults.Add(fooDelegate.BeginInvoke(a, b, c, null, null)); } // List to collect the result of each invocation var results = new List<double>(); // Wait for completion of all of the asynchronous invocations foreach (var asyncResult in asyncResults) { if (!asyncResult.CompletedSynchronously) { asyncResult.AsyncWaitHandle.WaitOne(); } // Collect the result of the invocation (results will appear in the list in the same order that the invocation was begun above. results.Add(fooDelegate.EndInvoke(asyncResult)); } // At this point, all of the asynchronous invocations have returned, and the result of each invocation is stored in the results list. 
Sign up to request clarification or add additional context in comments.

4 Comments

can you throw a loop around your example, this is what I need, but having trouble seeing how to loop it (have multiple function calls) when you're just sitting there waiting for the result of the first call.
@ganders I've made an edit to the answer to address your question. If you need further detail I'd suggest you post a separate question.
appreciate the quick response Iridium. Is the results variable in the while loop supposed to be the asyncResults variable instead?
@ganders yes, sorry, renamed it halfway through writing the answer. Edited to fix.
2

The answer to both of these questions is no, not with the native ThreadPool, although you can achieve the same result if you package your input args into the state object and write mechanisms to provide wait functionality and get the result of the work item method.

http://smartthreadpool.codeplex.com/ does everything you want;

 public static void Main(string[] args) { var threadPool = new SmartThreadPool(); IWorkItemResult<int> workItem=null; SmartThreadPool.WaitAll(new IWaitableResult[ ]{workItem = threadPool.QueueWorkItem(new Amib.Threading.Func<int, int, int>(Add), 1, 2)}); Console.WriteLine(workItem.Result); Console.ReadLine(); } public static int Add(int a, int b) { return a+b; } 

1 Comment

Thanks. I have used STP to good effect many times and it is a well regarded component stackoverflow.com/questions/8429938/…
0

Re your first question, create a new method of the correct signature (returns void, one object parameter) that calls foo. If you need to pass in specific arguments to foo then create a class or struct or use a Tuple<int, double, double> and cast it to object to pass it into ThreadMethod, then back to Tuple to get the arguments to foo.

void ThreadMethod(object obj) { var args = (Tuple<int, double, double>)obj; foo(args.Item1, args.Item2, args.Item3); } 

Re. 2nd question, you'd have to create the thread yourself so you can keep a Thread object to join with.

2 Comments

1. thats the point! my function has to be in this signature, I can't change it. 2. I want to insert it to the pool.
Create a new function that calls the one that can't change.
0

For the first question

I think you can create a new class as a parameter

for exsample

interface IAction { void Do(); } class SubClass : IAction { object _param; public SubClass(object o) { _param = o; } public void Do() { // your current code in here } } SubClass sc = new SubClass("paramter"); System.Threading.ThreadPool.QueueUserWorkItem(action => { var dosomething = action as IAction; dosomething.Do(); }, sc); 

So , you donnt need to change any code in your current function ...

Comments

0

The classic way of doing it is below, however as Iridium has shown there's more compact ways of doing it now. If you're using .NET 4 you can use the parallel APIs or more precisely Tasks to make it even easier.

public class MyWorker { private int _a; private double _b; private string _c; Action complete public MyWorker(int a,double b,string c) { _a = a; _b = b; _c = c; } public void Run(object state) { double result = Foo(); } private double Foo() { // Do something with _a, _b, _c } } MyWorker worker = new MyWorker(1,1,""); ThreadPool.QueueUserWorkItem(worker.Run); 

There's an equivalent example on the MSDN page.

In terms of being notified when a thread in a threadpool is completed, you can use a WaitHandle inside the object. Presumably you don't want to block until the thread is completed, in which case an event, Action or Func in the MyWorker class would be another solution.

I'd recommend reading Joe Albahari's free ebook on Threading as covers the subjects in a lot more detail.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.