TPL与TPL的区别异步/等待(线程处理) [英] Difference between the TPL & async/await (Thread handling)

查看:21
本文介绍了TPL与TPL的区别异步/等待(线程处理)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试图理解 TPL 和 TPL 之间的区别async/await 在创建线程时.

我相信 TPL (TaskFactory.StartNew) 的工作原理类似于 ThreadPool.QueueUserWorkItem,因为它在线程池中的线程上排队工作.当然,除非您使用 TaskCreationOptions.LongRunning 来创建一个新线程.

我认为 async/await 的工作原理类似:

TPL:

Factory.StartNew( () => DoSomeAsyncWork() ).继续((前因) =>{DoSomeWorkAfter();},TaskScheduler.FromCurrentSynchronizationContext());

Async/Await:

await DoSomeAsyncWork();DoSomeWorkAfter();

将是相同的.从我读过的内容来看,似乎 async/await 只有有时"会创建一个新线程.那么它什么时候创建一个新线程,什么时候不创建一个新线程呢?如果您正在处理 IO 完成端口,我可以看到它不必创建新线程,否则我认为它必须创建.我想我对 FromCurrentSynchronizationContext 的理解也总是有点模糊.我一直认为它本质上是 UI 线程.

解决方案

我相信 TPL (TaskFactory.Startnew) 的工作原理类似于 ThreadPool.QueueUserWorkItem,因为它在线程池中的线程上排队工作.

差不多.

<块引用>

从我一直在阅读的内容来看,似乎 async/await 只有有时"会创建一个新线程.

实际上,它从来没有.如果你想要多线程,你必须自己实现.有一个新的 Task.Run 方法,它只是 Task.Factory.StartNew 的简写,它可能是在线程池上启动任务的最常见方式.><块引用>

如果您正在处理 IO 完成端口,我可以看到它不必创建新线程,否则我认为它必须这样做.

宾果游戏.所以像 Stream.ReadAsync 这样的方法实际上会在 IOCP 周围创建一个 Task 包装器(如果 Stream 有一个 IOCP).

您还可以创建一些非 I/O、非 CPU 的任务".一个简单的例子是 Task.Delay,它返回一个在一段时间后完成的任务.

async/await 很酷的一点是你可以将一些工作排​​入线程池(例如,Task.Run),做一些 I/O 绑定的操作(例如,Stream.ReadAsync),并做一些其他的操作(例如,Task.Delay)......它们都是任务!它们可以等待或组合使用,例如 Task.WhenAll.

任何返回 Task 的方法都可以被 awaited - 它不必是 async 方法.所以 Task.Delay 和 I/O-bound 操作只使用 TaskCompletionSource 来创建和完成一个任务——线程池上唯一要做的就是实际任务完成时事件发生(超时、I/O 完成等).

<块引用>

我想我对 FromCurrentSynchronizationContext 的理解也总是有点模糊.我一直认为它本质上是 UI 线程.

我写了一篇文章关于SynchronizationContext.大多数时候,SynchronizationContext.Current:

  • 如果当前线程是 UI 线程,则为 UI 上下文.
  • 如果当前线程正在为 ASP.NET 请求提供服务,则为 ASP.NET 请求上下文.
  • 否则是线程池上下文.

任何线程都可以设置自己的SynchronizationContext,因此上述规则有例外.

请注意,默认的 Task 等待器将在当前 SynchronizationContext 上调度 async 方法的其余部分,如果它不为 null;否则它会继续当前的 TaskScheduler.这在今天并不那么重要,但在不久的将来,这将是一个重要的区别.

我自己写了async/await intro 在我的博客上,Stephen Toub 最近发布了一篇很棒的 async/await 常见问题.

关于并发"与多线程",请参阅此相关SO问题.我会说 async 启用并发性,它可能是也可能不是多线程的.使用 await Task.WhenAllawait Task.WhenAny 来做并发处理很容易,除非你明确使用线程池(例如,Task.RunConfigureAwait(false)),那么您可以同时进行多个并发操作(例如,多个 I/O 或其他类型,如 Delay)- 他们不需要线程.对于这种情况,我使用术语单线程并发",尽管在 ASP.NET 主机中,您实际上最终可能会得到线程并发".真是太甜了.

Trying to understanding the difference between the TPL & async/await when it comes to thread creation.

I believe the TPL (TaskFactory.StartNew) works similar to ThreadPool.QueueUserWorkItem in that it queues up work on a thread in the thread pool. That's of course unless you use TaskCreationOptions.LongRunning which creates a new thread.

I thought async/await would work similarly so essentially:

TPL:

Factory.StartNew( () => DoSomeAsyncWork() )
.ContinueWith( 
    (antecedent) => {
        DoSomeWorkAfter(); 
    },TaskScheduler.FromCurrentSynchronizationContext());

Async/Await:

await DoSomeAsyncWork();  
DoSomeWorkAfter();

would be identical. From what I've been reading it seems like async/await only "sometimes" creates a new thread. So when does it create a new thread and when doesn't it create a new thread? If you were dealing with IO completion ports i can see it not having to create a new thread but otherwise I would think it would have to. I guess my understanding of FromCurrentSynchronizationContext always was a bit fuzzy also. I always throught it was, in essence, the UI thread.

解决方案

I believe the TPL (TaskFactory.Startnew) works similar to ThreadPool.QueueUserWorkItem in that it queues up work on a thread in the thread pool.

Pretty much.

From what i've been reading it seems like async/await only "sometimes" creates a new thread.

Actually, it never does. If you want multithreading, you have to implement it yourself. There's a new Task.Run method that is just shorthand for Task.Factory.StartNew, and it's probably the most common way of starting a task on the thread pool.

If you were dealing with IO completion ports i can see it not having to create a new thread but otherwise i would think it would have to.

Bingo. So methods like Stream.ReadAsync will actually create a Task wrapper around an IOCP (if the Stream has an IOCP).

You can also create some non-I/O, non-CPU "tasks". A simple example is Task.Delay, which returns a task that completes after some time period.

The cool thing about async/await is that you can queue some work to the thread pool (e.g., Task.Run), do some I/O-bound operation (e.g., Stream.ReadAsync), and do some other operation (e.g., Task.Delay)... and they're all tasks! They can be awaited or used in combinations like Task.WhenAll.

Any method that returns Task can be awaited - it doesn't have to be an async method. So Task.Delay and I/O-bound operations just use TaskCompletionSource to create and complete a task - the only thing being done on the thread pool is the actual task completion when the event occurs (timeout, I/O completion, etc).

I guess my understanding of FromCurrentSynchronizationContext always was a bit fuzzy also. I always throught it was, in essence, the UI thread.

I wrote an article on SynchronizationContext. Most of the time, SynchronizationContext.Current:

  • is a UI context if the current thread is a UI thread.
  • is an ASP.NET request context if the current thread is servicing an ASP.NET request.
  • is a thread pool context otherwise.

Any thread can set its own SynchronizationContext, so there are exceptions to the rules above.

Note that the default Task awaiter will schedule the remainder of the async method on the current SynchronizationContext if it is not null; otherwise it goes on the current TaskScheduler. This isn't so important today, but in the near future it will be an important distinction.

I wrote my own async/await intro on my blog, and Stephen Toub recently posted an excellent async/await FAQ.

Regarding "concurrency" vs "multithreading", see this related SO question. I would say async enables concurrency, which may or may not be multithreaded. It's easy to use await Task.WhenAll or await Task.WhenAny to do concurrent processing, and unless you explicitly use the thread pool (e.g., Task.Run or ConfigureAwait(false)), then you can have multiple concurrent operations in progress at the same time (e.g., multiple I/O or other types like Delay) - and there is no thread needed for them. I use the term "single-threaded concurrency" for this kind of scenario, though in an ASP.NET host, you can actually end up with "zero-threaded concurrency". Which is pretty sweet.

这篇关于TPL与TPL的区别异步/等待(线程处理)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆