为什么从多个线程调用我的“StandardOleMarshalObject”COM 对象?

Why is my `StandardOleMarshalObject` COM Object called from multiple threads?

我有一个用 C# 实现的 COM 对象,它继承自 StandardOleMarshalObject 以禁用 NTA 默认行为。出于某种原因,当我调用对客户端进行可重入调用的服务器时,回调最终在不同的线程上结束。

如何确保所有调用都在主线程上进行?

[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IComChat
{
    void WriteLine(string text);
    void Subscribe(IComChat callback);
}

public class ComChatServer : StandardOleMarshalObject, IComChat
{
    private List<IComChat> Clients = new List<IComChat>();

    public void WriteLine(string text)
    {
        foreach (var client in Clients)
        {
            // this makes a reentrant callback into the calling client
            client.WriteLine(text);
        }
    }

    public void Subscribe(IComChat client) => Clients.Add(client);
}

public class ComChatClient : StandardOleMarshalObject, IComChat
{
    private IComChat Server;
    private Thread MainThread;

    public ComChatClient()
    {
        this.MainThread = Thread.CurrentThread;
        this.Server = /* get server by some means */;

        this.Server.Subscribe(this);
    }

    void IComChat.WriteLine(string text)
    {
        // this throws as the call ends up on a different thread
        Contract.Assert(Thread.CurrentThread == MainThread);

        Console.WriteLine(text);
    }

    void IComChat.Subscribe(IComChat callback) => throw new NotSupportedException();

    public void WriteLine(string text) => Server.WriteLine(text);
}

public static class Program
{
    public static void Main(string[] args)
    {
        var client = new ComChatClient();
        Application.Run(new ChatWindow(client));
    }
}
如果您在 STA 线程上创建对象,

StandardOleMarshalObject 只会将内容保留在主线程上。使用 [STAThread] 标记您的入口点以将您的主线程设置为单线程:

public static class Program
{
    [STAThread]
    public static void Main(string[] args)
    {
        var client = new ComChatClient();
        Application.Run(new ChatWindow(client));
    }
}