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

时间:2016-10-06 04:45:45

标签: c# .net com

我有一个用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));
    }
}

1 个答案:

答案 0 :(得分:0)

如果在STA线程上创建对象,

StandardOleMarshalObject仅保留主线程上的内容。使用[STAThread]标记入口点,将主线程设置为单线程:

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