将VirtualFileDataObject与async / await一起使用时出现“ COM对象与其基础RCW分离”错误

时间:2018-07-30 10:09:05

标签: com async-await .net-4.6

我正在尝试使用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

0 个答案:

没有答案