2011-12-21 80 views
1

我有两个问题:线程池在C#

  1. 有没有一种方法来插入ThreadPool functoin是这么想的获取 对象作为参数(插入函数线程池就必须返回void功能和ged一个参数 - 对象)例如,我想插入此函数:double foo(int a,double b,string c)
  2. 有没有一种方法wait线程池(如加入)?

回答

5

对于第一部分,最简单的方法可能是:

假设按你的描述方法:

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

你可以用线程池排队这样的:

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

对于第二个部分,虽然你不能在一个线程池线程等待,你可以在线程池上异步调用方法,并等待它们完成(这似乎是你正在寻找的)。

再次,假定Foo方法如上定义。

定义委托富:

// 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); 

为了解决在意见中提出的问题:

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

然后美孚异步使用FooDelegate的的BeginInvoke/EndInvoke会的方法来调用。如果你想在并行执行多个函数调用,并等待他们全部继续之前返回,你可以使用:

// 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. 
+0

你可以在你的例子中引入一个循环,这是我需要的,但是当你只是坐在那里等待第一次调用的结果时,看不到如何循环它(有多个函数调用)。 – ganders 2012-08-30 13:50:14

+1

@ganders我已经编辑了解答您的问题的答案。如果你需要进一步的细节,我建议你发布一个单独的问题。 – Iridium 2012-08-30 14:24:27

+0

欣赏铱星的快速反应。 while循环中的结果变量应该是asyncResults变量吗? – ganders 2012-08-30 14:57:21

2

这两个问题的答案都是否定的,不是原生的ThreadPool,尽管如果将输入参数包装到状态对象并写入机制以提供等待功能并获得结果时可以实现相同的结果的工作项目方法。

http://smartthreadpool.codeplex.com/做你想要的一切;

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; 
    } 
+0

+1仅供参考 – 2011-12-21 09:23:36

+0

谢谢。我已经使用STP很好的效果很多次,它是一个很好的组件http://stackoverflow.com/questions/8429938/maximum-concurrency-throttle – 2011-12-21 09:25:18

0

回复您的第一个问题,建立正确的签名的新方法(返回void,一个对象参数)调用foo。如果您需要将特定参数传递给foo,则创建一个类或结构或使用Tuple<int, double, double>并将其转换为对象以将其传递到ThreadMethod,然后返回Tuple以获取参数foo

void ThreadMethod(object obj) 
{ 
    var args = (Tuple<int, double, double>)obj; 

    foo(args.Item1, args.Item2, args.Item3); 
} 

Re。第二个问题,你必须自己创建线程,以便你可以保留一个Thread对象加入。

+0

1.多数民众赞成的重点!我的功能必须在这个签名中,我不能改变它。我想将它插入池中。 – aharon 2011-12-21 09:18:25

+0

创建一个调用无法更改的新函数。 – 2011-12-21 09:18:47

0

对于第一个问题

我想你可以创建一个新的类作为参数

为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); 

所以,你donnt需要更改您的当前功能的任何代码。 ..

0

做它的经典方法是下面,但铱星已经显示出有更紧凑的方式现在就做。如果您使用.NET 4,则可以使用并行API或更精确地使用Tasks以使其更容易。

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); 

MSDN page上有一个等效的例子。

在线程池中的线程完成时收到通知时,可以在对象内部使用WaitHandle 。大概你不想阻塞,直到线程完成,其中 事件,MyWorker类中的Action或Func将是另一个解决方案。

我建议阅读关于Threading的Joe Albahari's free ebook,因为它涵盖了更多细节的主题。