任务与 AsParallel()

发布于 2024-12-28 12:55:01 字数 818 浏览 1 评论 0原文

在 Stephen Toub 的书的第 33 页

http://www.microsoft.com/ download/en/details.aspx?id=19222

有代码

var pings = from addr in addrs.AsParallel().WithDegreeOfParallelism(16)
   select new Ping().Send(addr);
foreach (var ping in pings)
   Console.WriteLine("{0}: {1}", ping.Status, ping.Address);

,根据 Stephen 的说法,更好的版本

var pings = (from addr in addrs
    select new Ping().SendTask(addr, null)).ToArray();
Task.WaitAll(pings);
foreach (Task<PingReply> ping in pings)
    Console.WriteLine("{0}: {1}", ping.Result.Status, ping.Result.Address);

Stephen 说第二个选项更好,因为“任务抽象也可以用于表示 I/O 绑定操作,并且无需占用线程 但是任务

不是只使用底层的线程池(因此只是使用线程)吗?所以你实际上是在占用一个线程?

On page 33 of Stephen Toub's book

http://www.microsoft.com/download/en/details.aspx?id=19222

There is the code

var pings = from addr in addrs.AsParallel().WithDegreeOfParallelism(16)
   select new Ping().Send(addr);
foreach (var ping in pings)
   Console.WriteLine("{0}: {1}", ping.Status, ping.Address);

and according to Stephen the better version

var pings = (from addr in addrs
    select new Ping().SendTask(addr, null)).ToArray();
Task.WaitAll(pings);
foreach (Task<PingReply> ping in pings)
    Console.WriteLine("{0}: {1}", ping.Result.Status, ping.Result.Address);

Stephen says the 2nd option is better because "Task abstraction can also be used to represent I/O-bound operations and without tying up a thread in the
process."

But doesn't a Task just use the Threadpool(hence just using threads anyway) underneath anyway? So you are in fact tying up a thread?

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

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

发布评论

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

评论(1

也只是曾经 2025-01-04 12:55:01

并非所有任务都代表要在线程上完成的工作。几乎任何从 TaskCompletionSource 返回的任务都代表一些“其他”的东西。如果我们深入研究 SendTask 方法,我们会发现它调用 SentTaskCore

private static Task<PingReply> SendTaskCore(Ping ping, object userToken, Action<TaskCompletionSource<PingReply>> sendAsync)
    {
        // Validate we're being used with a real smtpClient.  The rest of the arg validation
        // will happen in the call to sendAsync.
        if (ping == null) throw new ArgumentNullException("ping");

        // Create a TaskCompletionSource to represent the operation
        var tcs = new TaskCompletionSource<PingReply>(userToken);

        // Register a handler that will transfer completion results to the TCS Task
        PingCompletedEventHandler handler = null;
        handler = (sender, e) => EAPCommon.HandleCompletion(tcs, e, () => e.Reply, () => ping.PingCompleted -= handler);
        ping.PingCompleted += handler;

        // Try to start the async operation.  If starting it fails (due to parameter validation)
        // unregister the handler before allowing the exception to propagate.
        try
        {
            sendAsync(tcs);
        }
        catch(Exception exc)
        {
            ping.PingCompleted -= handler;
            tcs.TrySetException(exc);
        }

        // Return the task to represent the asynchronous operation
        return tcs.Task;
    }

所以,不,它不会阻塞线程 - 它使用异步完成机制来避免占用一个线程。线。


来自 TaskCompletionSource 上的文档:

表示未绑定到委托的任务的生产者端,通过 Task 属性提供对消费者端的访问。

因此,正如它所说,它支持未绑定到委托的 Task - 它允许您将一个 Task 交给某人,然后编排该任务的完成方式,当完成涉及除执行委托之外的其他事情时。

Not all tasks represent work to be done on a thread. Just about any task returned from TaskCompletionSource represents something "other". And if we delve into the SendTask method, we find it calls SentTaskCore:

private static Task<PingReply> SendTaskCore(Ping ping, object userToken, Action<TaskCompletionSource<PingReply>> sendAsync)
    {
        // Validate we're being used with a real smtpClient.  The rest of the arg validation
        // will happen in the call to sendAsync.
        if (ping == null) throw new ArgumentNullException("ping");

        // Create a TaskCompletionSource to represent the operation
        var tcs = new TaskCompletionSource<PingReply>(userToken);

        // Register a handler that will transfer completion results to the TCS Task
        PingCompletedEventHandler handler = null;
        handler = (sender, e) => EAPCommon.HandleCompletion(tcs, e, () => e.Reply, () => ping.PingCompleted -= handler);
        ping.PingCompleted += handler;

        // Try to start the async operation.  If starting it fails (due to parameter validation)
        // unregister the handler before allowing the exception to propagate.
        try
        {
            sendAsync(tcs);
        }
        catch(Exception exc)
        {
            ping.PingCompleted -= handler;
            tcs.TrySetException(exc);
        }

        // Return the task to represent the asynchronous operation
        return tcs.Task;
    }

So, no, it's not blocking a thread - it's using the async completion mechanisms to avoid tying up a thread.


From the docs on TaskCompletionSource:

Represents the producer side of a Task unbound to a delegate, providing access to the consumer side through the Task property.

So, as it says, it supports a Task that isn't bound to a delegate - it allows you to hand someone a Task, and then orchestrate how that task gets completed, when completion involves something other than executing a delegate.

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