cod*_*fun 35 asynchronous task-parallel-library
我试图了解其目的TaskCompletionSource
及其与异步/无线工作的关系.我想我有一般的想法,但我想确保我的理解是正确的.
我首先开始研究任务并行库(TPL),以确定是否有一种很好的方法来创建自己的无线/异步工作(比如说你试图提高ASP.NET站点的可伸缩性)以及对TPL的理解看起来它将来会非常重要(async
/ await
).这导致我TaskCompletionSource
.
从我的理解来看,添加TaskCompletionSource
到你的一个类似乎没有做太多的编码异步; 如果您仍在执行同步代码,则对代码的调用将被阻止.我认为微软API也是如此.例如,假设在DownloadStringTaskAsync
关闭的WebClient
类,它们最初在做任何安装/同步代码将被阻塞.您正在执行的代码必须在某个线程上运行,无论是当前线程还是您必须分拆一个新线程.
因此TaskCompletionSource
,当您调用async
Microsoft的其他调用时,您可以在自己的代码中使用,这样您的类的客户端就不必为您的类创建一个新的线程来阻止它.
不确定Microsoft如何在内部执行异步API.例如,for .Net 4.5 有一种新async
方法SqlDataReader
.我知道有IO完成端口.我认为这可能是大多数C#开发人员不会使用的低级抽象(C++?).不确定IO完成端口是否适用于数据库或网络调用(HTTP),或者它是否仅用于文件IO.
所以问题是,我理解正确吗?是否有某些我错误表示的事情?
Ste*_*ary 59
TaskCompletionSource
用于创建Task
不执行代码的对象.
它们被微软新的异步API使用了很多 - 任何时候都有基于I/O的异步操作(或其他非基于CPU的异步操作,如超时).此外,async Task
您编写的任何方法都将使用TCS完成其返回Task
.
我有一篇博文" 创建任务",讨论了创建Task
实例的不同方法.它是从async
/ await
perspective(不是TPL的角度)编写的,但它仍然适用于此处.
另见Stephen Toub的优秀帖子:
TaskCompletionSource
到await
任何东西).Begin
/ End
使用TaskCompletionSource
).我喜欢http://tutorials.csharp-online.net/TaskCompletionSource中提供的解释
(对不起,链接可能已经死了)
前两段如下
我们已经看到Task.Run如何创建一个在池(或非池)线程上运行委托的任务.创建任务的另一种方法是使用TaskCompletionSource.
TaskCompletionSource允许您从任何启动并在稍后完成的操作中创建任务.它的工作原理是为您提供一个"奴隶"任务,您可以通过指示操作完成或故障来手动驱动.这是I/O绑定工作的理想选择:您可以获得任务的所有好处(具有传播返回值,异常和延续的能力),而不会在操作期间阻塞线程.
要使用TaskCompletionSource,您只需实例化该类.它公开了一个Task属性,该属性返回一个任务,您可以在该任务上等待并附加continuation - 就像任何其他任务一样.但是,该任务完全由TaskCompletionSource对象通过以下方法控制:
public class TaskCompletionSource<TResult>
{
public void SetResult(TResult result);
public void SetException (Exception exception);
public void SetCanceled();
public bool TrySetResult (TResult result);
public bool TrySetException (Exception exception);
public bool TrySetCanceled();
...
}
Run Code Online (Sandbox Code Playgroud)
调用任何这些方法都会发出任务信号,将其置于完成,故障或取消状态(我们将在"取消"部分中介绍后者).你应该只调用其中一种方法:如果再次调用,SetResult,SetException或SetCanceled将抛出异常,而Try*方法返回false.
以下示例在等待五秒后打印42:
var tcs = new TaskCompletionSource<int>();
new Thread (() => {
Thread.Sleep (5000);
tcs.SetResult (42);
})
.Start();
Task<int> task = tcs.Task; // Our "slave" task.
Console.WriteLine(task.Result); // 42
Run Code Online (Sandbox Code Playgroud)
其他有趣的报价
TaskCompletionSource的真正强大之处在于创建不会占用线程的任务.
..以及后来
我们在没有线程的情况下使用TaskCompletionSource意味着只有在五秒钟之后继续开始时才使用线程.我们可以通过一次启动10,000个这样的操作来证明这一点,没有错误或过多的资源消耗:
归档时间: |
|
查看次数: |
19792 次 |
最近记录: |