- VB.NET(即使截至2023年8月)不支持在
Using
中使用IAsyncDisposable
。
- 它也不支持在
Finally
中使用Await
。
- 所以你能做的最好办法是尝试一些丑陋的技巧和/或将一些旧的C#技巧移植过来 some old C# tricks...
方法1:使用C#处理using
部分:
只需创建一个新的空C#类库项目,其中包含一个可以从VB.NET调用的辅助方法,类似于以下内容:
(只是不要指望能够使用ConfigureAwait(False)
- 即使在C#中也很困难)。
public static class ArghExtensions
{
public static async Task UsingAsyncDisposableAsync( this IAsyncDisposable subject, CancellationToken cancellationToken, Func<CancellationToken,Task> asyncBody )
{
await using( subject )
{
if( subject is null ) throw new ArgumentNullException(nameof(subject));
if( asyncBody is null ) throw new ArgumentNullException(nameof(asyncBody));
await asyncBody( cancellationToken ).ConfigureAwait(false);
}
}
}
然后从VB.NET中调用它:
Imports ArghExtensions
Async Function FoobarAsync( cancellationToken As CancellationToken ) As Task
Dim d AS IAsyncDisposable = GetSomethingDisposable()
Await d.UsingAsyncDisposableAsync( Async Function( ct As CancellationToken )
End Function )
End Function
另一种实现这个方法的替代方式,而不使用任何C#步骤,是在VB.NET中使用Reflection.Emit来生成等效(且安全)的IL代码,重新实现UsingAsyncDisposableAsync
方法 - 尽管这可能需要很多工作,但收益可能很小。
方法二:拥抱VB.NET的“冗长”
与其使用任何C#代码,我们实际上可以完全在VB.NET中完成所有操作,但需要注意的是,你需要使用Try/Catch
而不是Try/Finally
,因为VB.NET仍然无法在Finally
块中使用Await
:
Async Function FoobarAsync( cancellationToken As CancellationToken ) As Task
Dim capturedException As ExceptionDispatchInfo = Nothing
Dim d AS IAsyncDisposable = GetSomethingDisposable()
Try
Await d.DisposeAsync().ConfigureAwait(False)
d = Nothing
Catch x As Exception
capturedException = ExceptionDispatchInfo.Capture( x )
End Try
If capturedException IsNot Nothing Then
If d IsNot Nothing Then
Await d.DisposeAsync().ConfigureAwait(False)
d = Nothing
End If
capturedException.Throw()
End If
End Function
Function GetSomethingDisposable() As IAsyncDisposable
Return New MemoryStream()
End Function
我还没有对这段代码进行任何静态分析,但我有信心这不会触发CA2000
Async
扩展方法、Try/Finally
和回调地狱来拼凑一些东西,但显然与C#不同,VB.NET仍然不允许在Finally
块中使用Await
(用于Await disposable.DisposeAsync()
)。有一些解决方案适用于C#具有相同限制的情况,这些解决方案也适用于VB.NET,但对我来说变得太繁琐了,所以我放弃了,很抱歉。因此,我认为这是一个更严肃地迁移到VB.NET之外的时机。 - Dai