2011-01-21 48 views
2

假设我有一个方法,比如ThreadPool.QueueTask(Delegate d)。我写了一个线程池,如何通知使用它的方法,任务已完成?

其中一些代表需要返回值,但由于他们无法做到这一点(作为委托传递),他们将需要通过引用将值作为参数。一旦任务完成,这个值将被改变,所以调用方法需要知道这一点。

实质上,将任务传递给线程池的方法应该等待,直到它完成。

这样做的最好方法是什么?我应该只是做Threadpool.QueueTask(Delegate d,EventWaitHandle e),还是有一种更优雅的方式,对于那些不熟悉这种事情的人来说显而易见?

亲切的问候, 府谷

+1

是否有任何理由不能使用TPL来做到这一点?如果这对您有用,我可以提出一个好的解决方案。 – 2011-01-21 15:51:32

+0

什么是TPL? – Fugu 2011-01-21 15:55:11

回答

5

您可以使用ManualResetEvent

public void TaskStartMethod() 
{ 
    ManualResetEvent waitHandle = new ManualResetEvent(false); 

    ThreadPool.QueueUserWorkItem(o=> 
    { 
     // Perform the task here 

     // Signal when done 
     waitHandle.Signal(); 
    }); 

    // Wait until the task is complete 
    waitHandle.WaitOne(); 
} 

从本质上讲,传递 任务线程池的方法应该是 等待,直到它完成。

上面的代码是这样做的,但现在我有一个问题:如果您的方法正在等待任务完成,那么为什么你甚至懒得在单独的线程上执行任务?换句话说,你所描述的是代码的顺序执行而不是并行执行,所以使用ThradPool是毫无意义的。

或者,你可能可能需要使用一个单独的委托作为回调:

public delegate void OnTaskCompleteDelegate(Result someResult); 

public void TaskStartMethod() 
{ 
    OnTaskCompleteDelegate callback = new OnTaskCompleteDelegate(OnTaskComplete); 
    ThradPool.QueueUserWorkItem(o=> 
    { 
     // Perform the task 

     // Use the callback to notify that the 
     // task is complete. You can send a result 
     // or whatever you find necessary. 
     callback(new Result(...)); 
    }); 

} 

public void OnTaskComplete(Result someResult) 
{ 
    // Process the result 
} 

更新(2011/1/24): 你可能甚至不需要回调委托,你可以直接调用OnTaskComplete和应该做的工作太多:

public void TaskStartMethod() 
{ 
    ThradPool.QueueUserWorkItem(o=> 
    { 
     // Perform the task 

     // Call the method when the task is complete 
     OnTaskComplete(new Result(...)); 
    }); 
} 
1

取决于你是如何做的。对我来说,听起来有点像你有线程A把一个任务放到线程池中,然后等待它完成。这听起来不是很有帮助。如果你在线程池中放置一个任务并等待,只需在你自己的线程中完成。

但这可能不是你在做什么!

我可以看到使用线程池的两种可能的好方法。线程A有多件事情要并行启动,然后等待它们全部完成。在这种情况下,您需要为所有任务(或结果类)存储句柄,因此您可以等待它们全部完成。你可以使用semiphores或各种同步工具(我不专门做c#)以避免忙于轮询。

另一种方法是在任务结束时使用回调。线程A启动线程池上的任务,然后存在。任务有一个返回给它的类的句柄,当它完成时调用一个回调类型函数来完成最终化类型的东西。

相关问题