在我看过的每个展示中都使用async / await进行I / O阻塞调用,最后有一个虚拟调用(Task.Delay)或一个支持某些异步的API图案。但是,如果你有一个API有I / O阻塞方法,但是没有提供任何你可以等待或以某种方式包装的东西,以便你可以等待它呢?我知道TaskCompletionSource应该是解决这个问题的方法,但是我还没有发现任何真正解释它(无论如何)它是如何工作的。我试过了
var tcs = new TaskCompletionSource<SomeType>();
try
{
tcs.SetResult(IoBlockingCall());
}
catch (Exception ex)
{
tcs.SetException(ex);
}
return tcs.Task;
上面的代码在tcs.SetResult()之后立即返回的意义上不起作用。很明显我错过了一些东西,但我还没有找到一个如何做到这一点的例子,它不依赖于你已经有一个方法在启动一些I / O阻塞操作后立即返回。我猜一个问同样问题的简单方法是,如果我不得不写SqlConnection.OpenAsync,我该怎么办?
(注意,请不要回答Task.Run()。这是关于I / O阻塞,而不是卸载。谢谢!)
对于其他评论者,我在这里想要完成的是不启动另一个线程。这样做是微不足道的,但是会破坏async / await的主要目的是阻止I / O. (见There Is No Thread)。这让我觉得如果不突破.NET的底部就可能是不可能的,而根据@PetSerAl就是这样。
答案 0 :(得分:-3)
那是聊天Task.Yield
。
你可以试试这个:
Task.Yield();
var tcs = new TaskCompletionSource<SomeType>();
try
{
tcs.SetResult(IoBlockingCall());
}
catch (Exception ex)
{
tcs.SetException(ex);
}
return tcs.Task;
但这可能无法按预期工作(请阅读文档中的备注部分)。在某些情况下,Task.Delay(0)
会更有效。
由于IoBlockingCall
正在阻止,因此对于大多数意图和目的,您需要卸载它。或者不是,就像在ASP.NET中卸载没有任何好处一样。