EDITED, MSDN:
. , SHCreateMemStream, Windows 8. . , CreateStreamOnHGlobal, .
, . , @HansPassant , @IInpectable . , IStream.
:
, IStream . .
MTA, IStream from thread unmarshaled thread2 IUnknown, .
thread1 - STA, thread2 - MTA, . , thread, - thread2.
, stream1 , . , , /. , , , IStream, CreateStreamOnHGlobal, .
, COM IStream, , - , CreateStreamOnHGlobal.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void TestStream()
{
var thread1 = new Thread(() =>
{
System.Runtime.InteropServices.ComTypes.IStream stream1;
CreateStreamOnHGlobal(IntPtr.Zero, true, out stream1);
IntPtr unkStream1 = Marshal.GetIUnknownForObject(stream1);
Guid iid = typeof(System.Runtime.InteropServices.ComTypes.IStream).GUID;
System.Runtime.InteropServices.ComTypes.IStream marshallerStream;
CoMarshalInterThreadInterfaceInStream(ref iid, stream1, out marshallerStream);
var buf1 = new byte[] { 1, 2, 3, 4 };
stream1.Write(buf1, buf1.Length, IntPtr.Zero);
var thread2 = new Thread(() =>
{
var buf2 = new byte[buf1.Length];
for (var i = 0; i < 10000; i++)
{
stream1.Seek(0, 0, IntPtr.Zero);
stream1.Read(buf2, buf2.Length, IntPtr.Zero);
for (var j = 0; j < buf2.Length; j++)
Debug.Assert(buf1[j] == buf2[j]);
}
object stream2;
CoGetInterfaceAndReleaseStream(marshallerStream, ref iid, out stream2);
IntPtr unkStream2 = Marshal.GetIUnknownForObject(stream2);
Debug.Assert(unkStream1 == unkStream2);
Marshal.Release(unkStream2);
});
for (var i = 0; i < 10000; i++)
{
stream1.Seek(0, 0, IntPtr.Zero);
stream1.Write(buf1, buf1.Length, IntPtr.Zero);
}
thread2.SetApartmentState(ApartmentState.MTA);
thread2.Start();
thread2.Join();
Marshal.Release(unkStream1);
});
thread1.SetApartmentState(ApartmentState.STA);
thread1.Start();
thread1.Join();
}
static void Main(string[] args)
{
TestStream();
}
[DllImport("ole32.dll", PreserveSig = false)]
public static extern void CreateStreamOnHGlobal(
IntPtr hGlobal,
bool fDeleteOnRelease,
[Out] out System.Runtime.InteropServices.ComTypes.IStream pStream);
[DllImport("ole32.dll", PreserveSig = false)]
public static extern void CoMarshalInterThreadInterfaceInStream(
[In] ref Guid riid,
[MarshalAs(UnmanagedType.IUnknown)] object unk,
out System.Runtime.InteropServices.ComTypes.IStream stream);
[DllImport("ole32.dll", PreserveSig = false)]
public static extern void CoGetInterfaceAndReleaseStream(
[In] System.Runtime.InteropServices.ComTypes.IStream stream,
[In] ref Guid riid,
[Out, MarshalAs(UnmanagedType.IUnknown)] out object unk);
}
}