我编写了一个线程池,如何通知使用它的方法任务已完成?

发布于 2024-10-13 05:35:16 字数 304 浏览 4 评论 0原文

假设我有一个方法,例如 ThreadPool.QueueTask(Delegate d)。

其中一些委托需要返回值,但由于它们无法执行此操作(作为委托传递),因此它们需要通过引用获取值作为参数。一旦任务完成,该值将被更改,因此调用方法需要知道这一点。

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

最好的方法是什么?我应该只做 Threadpool.QueueTask(Delegate d, EventWaitHandle e) 吗?或者是否有一种更优雅的方法,对于不熟悉此类事情的人来说是显而易见的?

亲切的问候, 河豚

So let's say I have a method such as ThreadPool.QueueTask(Delegate d).

Some of these delegates need to return values, but as they cannot do this (being passed as delegates) they will need to take a value by reference as a parameter. Once the task is completed this value will have been altered, so the calling method needs to know this.

Essentially, the method passing the task to the threadpool should be waiting until it has completed.

What is the best way to do this? Should I just do Threadpool.QueueTask(Delegate d, EventWaitHandle e), or is there a more elegant way which would be obvious to people unfamiliar with that kind of thing?

Kind regards,
Fugu

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

段念尘 2024-10-20 05:35:16

您可以使用 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
}

更新 (1/24/2011):
您甚至可能不需要回调委托,您可以直接调用 OnTaskComplete ,这也应该可以完成这项工作:

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

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

You can use a 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();
}

Essentially, the method passing the
task to the threadpool should be
waiting until it has completed.

The above code does that, but now I have a question: if your method is waiting for the task to be completed, then why do you even bother to perform the task on a separate thread? In other words, what you're describing is sequential execution of code rather than parallel, so the use of the ThradPool is pointless.

Alternately, you might might want to use a separate delegate as a callback:

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
}

Update (1/24/2011):
You might not even need the callback delegate, you can just directly call OnTaskComplete and that should do the job too:

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

        // Call the method when the task is complete
        OnTaskComplete(new Result(...));
    });
}
真心难拥有 2024-10-20 05:35:16

取决于你如何做。对我来说,这听起来有点像您让线程 A 将单个任务放入线程池中,然后等待该任务完成。这听起来不太有帮助。如果您将一项任务放入线程池并等待,只需在您自己的线程中执行即可。

但这可能不是你所做的!

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

另一种方法是在任务结束时使用回调。线程A启动线程池中的任务,然后存在。该任务有一个返回启动它的类的句柄,并在完成时调用回调类型函数来执行终结类型的操作。

Depends on how you are doing it. To me it sounds a little like you have thread A putting a single task on the thread pool, then waiting for that to finish. That does not sound very helpful. If you are putting one task on the thread pool and waiting, just do it in your own thread.

But that is probably not what your doing!

I can see two possible good ways for using the thread pool. Thread A has multiple things that it wants to kick off in parallel, and then wait for them all to finish. In this case you need to store a handle to all of the tasks (or a result class), so you can wait for them all to finish. You can make use of semiphores or various synchronization tools (I don't do c# specifically) to avoid having to busy poll.

Another way is to use a callback at the end of the task. Thread A kicks off the task on the thread pool, then exists. The task has a handle back to the class that kicked it off, and calls a callback type function when it is completed to do finalisation type stuff.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文