我正在尝试使用David Anson的VirtualFileDataObject
(在this NuGet package中提供),但是我遇到了一些问题。将async void
传递到StreamContents
属性时,会发生一种情况。可以正常工作:
Dim descriptor As New VirtualFileDataObject.VirtualFileDataObject.FileDescriptor With {
.Name = info.FileName,
.StreamContents = Sub(s)
Dim d As New FileTransfer.Downloader(info.BildID)
Dim fs = d.DownloadSingleAsync().GetAwaiter().GetResult()
fs.Position = 0
fs.CopyTo(s)
End Sub}
(Downloader是一个使用Web服务获取数据的类。它不相关,因为DownloadSingleAsync
返回了一个任务Stream
。)
但是,当然GetAwaiter()
并不是您应该等待的东西。
但是,这是
Dim descriptor As New VirtualFileDataObject.VirtualFileDataObject.FileDescriptor With {
.Name = info.FileName,
.StreamContents = Async Sub(s)
Dim d As New FileTransfer.Downloader(info.BildID)
Dim fs = Await d.DownloadSingleAsync().ConfigureAwait(False)
fs.Position = 0
Await fs.CopyToAsync(s).ConfigureAwait(False)
End Sub}
…将引发COMException。
我的猜测是有些东西发布得太早了。我发现了this piece of code:
// Return an IntPtr for the IStream
ptr = Marshal.GetComInterfaceForObject(iStream, typeof(IStream));
Marshal.ReleaseComObject(iStream);
也许ReleaseComObject
被调用太早。我可以打电话(也许类似于GC.SuppressFinalize()
吗?)来阻止COM对象在完成之前被释放?
(编辑)根据要求,显示堆栈跟踪:
System.Runtime.InteropServices.InvalidComObjectException
HResult=0x80131527
Message=COM object that has been separated from its underlying RCW cannot be used.
Source=mscorlib
StackTrace:
at System.StubHelpers.StubHelpers.StubRegisterRCW(Object pThis)
at System.Runtime.InteropServices.ComTypes.IStream.Write(Byte[] pv, Int32 cb, IntPtr pcbWritten)
at System.IO.Stream.<>c.<BeginWriteInternal>b__46_0(Object )
at System.Threading.Tasks.Task`1.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.IO.Stream.EndWrite(IAsyncResult asyncResult)
at System.IO.Stream.<>c.<BeginEndWriteAsync>b__53_1(Stream stream, IAsyncResult asyncResult)
at System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.Complete(TInstance thisRef, Func`3 endMethod, IAsyncResult asyncResult, Boolean requiresSynchronization)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
at MyApp.Bilder._Closure$__178-0.VB$StateMachine___Lambda$__0.MoveNext() in Bilder.vb:line 467