gpt4 book ai didi

c# - IO 异步方法中的 TaskCompletionSource 用法

转载 作者:太空宇宙 更新时间:2023-11-03 23:22:29 26 4
gpt4 key购买 nike

执行ExecuteNonQueryAsync() System.Data.SqlClient.SqlCommand 中的方法如下:

    public override Task<int> ExecuteNonQueryAsync(CancellationToken cancellationToken) {

Bid.CorrelationTrace("<sc.SqlCommand.ExecuteNonQueryAsync|API|Correlation> ObjectID%d#, ActivityID %ls\n", ObjectID);
SqlConnection.ExecutePermission.Demand();

TaskCompletionSource<int> source = new TaskCompletionSource<int>();

CancellationTokenRegistration registration = new CancellationTokenRegistration();
if (cancellationToken.CanBeCanceled) {
if (cancellationToken.IsCancellationRequested) {
source.SetCanceled();
return source.Task;
}
registration = cancellationToken.Register(CancelIgnoreFailure);
}

Task<int> returnedTask = source.Task;
try {
RegisterForConnectionCloseNotification(ref returnedTask);

Task<int>.Factory.FromAsync(BeginExecuteNonQueryAsync, EndExecuteNonQueryAsync, null).ContinueWith((t) => {
registration.Dispose();
if (t.IsFaulted) {
Exception e = t.Exception.InnerException;
source.SetException(e);
}
else {
if (t.IsCanceled) {
source.SetCanceled();
}
else {
source.SetResult(t.Result);
}
}
}, TaskScheduler.Default);
}
catch (Exception e) {
source.SetException(e);
}

return returnedTask;
}

我总结为:

  1. Create TaskCompletionSource<int> source = new TaskCompletionSource<int>();
  2. Create a new task using Task<int>.Factory.FromAsync, using the APM "Begin/End" API
  3. Invoke source.SetResult() when the task finishes.
  4. Return source.Task

使用 TaskCompletionSource 有什么意义?这里以及为什么不返回 Task<int>.Factory.FromAsync() 创建的任务直接地?此任务还包装了结果和异常(如果有)。

在 C# in a Nutshell 一书中,Asynchronous Programming and Continuations 部分指出:

In writing Delay, we used TaskCompletionSource, which is a standard way to implement “bottom-level” I/O-bound asynchronous methods.

For compute-bound methods, we use Task.Run to initiate thread-bound concurrency. Simply by returning the task to the caller, we create an asynchronous method.

为什么可以使用 Task.Run() 实现计算绑定(bind)方法? ,但不是 I/O 绑定(bind)方法?

最佳答案

请注意,要获得明确的答案,您必须询问代码的作者。除此之外,我们只能推测。但是,我认为以合理的准确性做出一些推断是合理的……

What is the point of using TaskCompletionSource here and why not to return the task created by Task.Factory.FromAsync() directly?

在这种情况下,在我看来,主要原因是允许实现在任务实际完成之前注销已注册的回调 CancelIgnoreFailure()。这可确保在客户端代码收到完成通知时,API 本身已从操作中完全清除。

第二个原因可能只是为了提供一个完整的抽象。 IE。不允许 任何 底层实现以 Task 对象的形式从方法中“泄漏”,调用者可能会以某种方式检查或(更糟)操作干扰任务的正确和可靠操作。

Why is it that the compute-bound methods can be implemented using Task.Run(), but not the I/O bound methods?

可以使用 Task.Run() 实现 I/O 绑定(bind)操作,但为什么要这么做?这样做会将一个线程提交给该操作,对于一个不需要线程的操作来说,这是一种浪费。

I/O 绑定(bind)操作通常有 I/O 完成端口和 IOCP 线程池(其中的线程处理任意数量的 IOCP 的完成)的支持,因此简单地使用现有的异步更有效I/O API,而不是使用 Task.Run() 来调用同步 I/O 方法。

关于c# - IO 异步方法中的 TaskCompletionSource 用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34943935/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com