从处理外的进程内COM服务器事件管理STA应用进程、事件、服务器、STA

2023-09-02 01:37:30 作者:人潮拥挤我踹死你

显然,管理处理的事件,从非托管了进程外COM服务器采购的,被称为回随机池线程,而不是主STA线程上(如我期望)。 我发现这一点的同时回答有关 Internet Explorer的自动化。在code以下,的DocumentComplete 被激发在非UI线程(让事件线程是不一样的主线程在调试输出)。因此,我必须使用 this.Invoke 来显示一个消息框。尽我所知,这种行为是从非托管COM客户端,在事件订阅从一个STA线程会自动整理回到同一线程不同。

什么是落后于传统的COM行为,离职的原因吗?到目前为止,我还没有发现任何引用证实这一点。

 使用系统;
使用System.Diagnostics程序;
使用的System.Threading;
使用System.Windows.Forms的;

命名空间WinformsIE
{
    公共部分类Form1中:形态
    {
        公共Form1中()
        {
            的InitializeComponent();
        }

        私人无效Form1_Load的(对象发件人,EventArgs EV)
        {
            VAR即= (SHDocVw.InternetExplorer)Activator.CreateInstance(Type.GetTypeFromProgID("InternetExplorer.Application"));
            ie.Visible =真;
            Debug.Print(主要思路:{0},Thread.CurrentThread.ManagedThreadId);
            ie.DocumentComplete + =(对象浏览器,参考目标URL)=>
            {
                字符串URL = URL.ToString();
                Debug.Print(事件线程:{0},Thread.CurrentThread.ManagedThreadId);
                this.Invoke(新动作(()=>
                {
                    Debug.Print(行动主题:{0},Thread.CurrentThread.ManagedThreadId);
                    VAR消息=的String.Format(页面加载:{0},网址);
                    的MessageBox.show(消息);
                }));
            };
            ie.Navigate(http://www.example.com);
        }
    }
}
 

解决方案

我发现从以下摘录亚当森的.NET和COM:完全互操作性指南:

  

如果COM对象住在一个STA,从MTA线程任何呼叫   封适当所以COM对象保持其世界   线程关联。但是,在其他方向,没有这样的螺纹或   上下文切换发生。

因此​​,这是预期的行为。到目前为止,这是关于这个问题我能找到的唯一(半官方)的来源。

高性能服务器架构思路丨缓冲策略

Apparently, managed handlers for events, sourced from an unmanaged out-of-process COM server, are called back on a random pool thread, rather than on the main STA thread (as I'd expect). I've discovered this while answering a question on Internet Explorer automation. In the code below, DocumentComplete is fired on a non-UI thread (so "Event thread" is not the same as "Main thread" in the debug output). Thus, I have to use this.Invoke to show a message box. To the best of my knowledge, this behavior is different from unmanaged COM clients, where events subscribed to from an STA thread are automatically marshalled back to the the same thread.

What is the reason behind such departure from the traditional COM behavior? So far, I haven't found any references confirming this.

using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;

namespace WinformsIE
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs ev)
        {
            var ie = (SHDocVw.InternetExplorer)Activator.CreateInstance(Type.GetTypeFromProgID("InternetExplorer.Application"));
            ie.Visible = true;
            Debug.Print("Main thread: {0}", Thread.CurrentThread.ManagedThreadId);
            ie.DocumentComplete += (object browser, ref object URL) =>
            {
                string url = URL.ToString();
                Debug.Print("Event thread: {0}", Thread.CurrentThread.ManagedThreadId);
                this.Invoke(new Action(() =>
                {
                    Debug.Print("Action thread: {0}", Thread.CurrentThread.ManagedThreadId);
                    var message = String.Format("Page loaded: {0}", url);
                    MessageBox.Show(message);
                }));
            };
            ie.Navigate("http://www.example.com");
        }
    }
}

解决方案

I've found the following excerpt from Adam Nathan's ".NET and COM: The Complete Interoperability Guide":

If the COM object lives in an STA, any calls from MTA threads are marshaled appropriately so the COM object remains in its world of thread affinity. But, in the other direction, no such thread or context switch occurs.

Thus, this is the expected behavior. So far, that's the only (semi-official) source on the subject I could find.