【发布时间】:2012-01-25 02:45:10
【问题描述】:
我有两个问题:
- 有没有办法插入一个无法获得的
ThreadPoolfunctoin 对象作为参数(要向线程池插入一个函数,它需要是返回 void 和一个参数 - 对象的函数)例如我想插入这个函数:double foo(int a,double b,string c)? - 有没有办法让
wait在池中线程(如加入)?
【问题讨论】:
标签: c# threadpool
我有两个问题:
ThreadPool functoin
对象作为参数(要向线程池插入一个函数,它需要是返回 void 和一个参数 - 对象的函数)例如我想插入这个函数:double foo(int a,double b,string c)? wait 在池中线程(如加入)?【问题讨论】:
标签: c# threadpool
这两个问题的答案是否定的,不是使用原生 ThreadPool,虽然如果你将输入的 args 打包到状态对象中并编写机制以提供等待功能并获得工作结果,则可以达到相同的结果项目方法。
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;
}
【讨论】:
关于您的第一个问题,创建一个调用foo 的正确签名的新方法(返回void,一个对象参数)。如果您需要将特定参数传递给 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);
}
回复。第二个问题,你必须自己创建线程,这样你才能保留一个Thread 对象来加入。
【讨论】:
第一个问题
我认为你可以创建一个新类作为参数
示例
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);
因此,您无需更改当前函数中的任何代码...
【讨论】:
对于第一部分,最简单的方法可能是:
根据您的描述假设一种方法:
public double foo(int a, double b, string c)
{
...
}
你可以在线程池中排队:
ThreadPool.QueueUserWorkItem(o => foo(a, b, c));
对于第二部分,虽然您不能在 ThreadPool 线程上等待,但您可以在线程池上异步调用方法,并等待它们完成(这似乎是您要寻找的)。
再次假设Foo 方法定义如上。
为 Foo 定义一个委托:
private delegate double FooDelegate(int a, double b, string c);
然后使用 FooDelegate 的 BeginInvoke/EndInvoke 方法异步调用 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);
解决 cmets 中提出的问题。如果您想并行执行多个函数调用并等待它们全部返回后再继续,您可以使用:
// 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.
【讨论】:
执行此操作的经典方式如下所示,但正如 Iridium 所展示的,现在有更紧凑的方式执行此操作。如果您使用的是 .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 将是另一种解决方案。
我建议阅读有关线程的Joe Albahari's free ebook,因为它更详细地涵盖了这些主题。
【讨论】: