问题描述
在 ASP.NET 4.5 中,我正在尝试使用新的异步/等待玩具.我有一个 IDataReader 实现类,它包装了一个特定于供应商的阅读器(如 SqlDatareader).我有一个简单的 ExecuteSql() 方法,它像这样同步操作:
With ASP.NET 4.5 I'm trying to play with the new async/await toys. I have a IDataReader-implementing class that wraps a vendor-specific reader (like SqlDatareader). I have a simple ExecuteSql() method that operates synchronously like so:
public IDataReader ReaderForSql(string sql)
{
var cmd = NewCommand(sql, CommandType.Text);
return DBReader.ReaderFactory(cmd.ExecuteReader());
}
我想要的是这个的异步版本.这是我的第一次尝试:
What I want is an Async version of this. Here's my first try:
public Task<IDataReader> ReaderForSqlAsync(string sql, CancellationToken ct)
{
var cmd = NewCommand(sql, CommandType.Text);
return cmd.ExecuteReaderAsync(ct)
.ContinueWith(t => DBReader.ReaderFactory(t.Result));
}
我使用它:
using (var r = await connection.ReaderForSqlAsync("SELECT ...", cancellationToken))
{
...
}
到目前为止,这在我有限的测试中效果很好.但是在看了几次这个 Cloud9 视频后:http://channel9.msdn.com/Events/aspConf/aspConf/Async-in-ASP-NET 我很担心他们给出的警告:
This works great in my limited testing so far. But after watching this Cloud9 video a few times: http://channel9.msdn.com/Events/aspConf/aspConf/Async-in-ASP-NET I got worreid about warnings they gave regarding:
- 继续消耗额外的线程池资源 - Readerfactory 非常轻!
- Task.Result 阻塞
并且由于我将 ContinuationToken 传递给 ExecuteReaderAsync() 似乎取消只是 ExecuteReaderAsync() 可能失败的另一个原因(毕竟是 SQL!)
and since I am passing a ContinuationToken to ExecuteReaderAsync() it seems cancellation is just yet another reason ExecuteReaderAsync() could fail (it's SQL after all!)
当我尝试 ContinueWith 时任务的状态是什么?t.Result 会阻塞吗?扔?做错事了吗?
What will be the state of the task when I try to ContinueWith it? Will t.Result block? throw? do the wrong thing?
推荐答案
ContinueWith
默认会使用当前的任务调度器(一个线程池线程),但你可以通过传递 来改变它TaskContinuationOptions.ExecuteSynchronously
和显式的 TaskScheduler
.
ContinueWith
will use the current task scheduler (a thread pool thread) by default, but you can change that by passing TaskContinuationOptions.ExecuteSynchronously
and an explicit TaskScheduler
.
也就是说,我会把它作为第一次尝试:
That said, I would make this as a first effort:
public async Task<IDataReader> ReaderForSqlAsync(string sql, CancellationToken ct)
{
var cmd = NewCommand(sql, CommandType.Text);
var readerResult = await cmd.ExecuteReaderAsync(ct).ConfigureAwait(false);
return DBReader.ReaderFactory(readerResult);
}
async
和 await
以一致的方式为您处理所有 ContinueWith
细节和边缘条件.可能会将此代码复杂化以使其更快如果性能测试表明这是一个严重的问题.
async
and await
handle all the ContinueWith
delicacies and edge conditions in a consistent manner for you. It may be possible to complicate this code to be faster if performance testing indicates it's a serious problem.
这篇关于任务.继续混乱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!