4

どうやら、管理されていないアウトプロセス COM サーバーから供給されたイベントの管理されたハンドラーは、メインの STA スレッドではなく、ランダム プール スレッドでコールバックされるようです (予想どおり)。Internet Explorer の自動化に関する質問に回答しているときに、これを発見しました。以下のコードでDocumentCompleteは、非 UI スレッドで起動されます (したがって、デバッグ出力とは異なります) "Event thread""Main thread"したがって、this.Invokeメッセージボックスを表示するために使用する必要があります。私の知る限り、この動作は、STA スレッドからサブスクライブされたイベントが自動的に同じスレッドにマーシャリングされるアンマネージ COM クライアントとは異なります。

従来の COM の動作からこのように逸脱した理由は何ですか? これまでのところ、これを確認する参考文献は見つかりませんでした。

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");
        }
    }
}
4

1 に答える 1

2

Adam Nathan の「.NET and COM: The Complete Interoperability Guide」から次の抜粋を見つけました。

COM オブジェクトが STA に存在する場合、MTA スレッドからの呼び出しは適切にマーシャリングされるため、COM オブジェクトはスレッド アフィニティの世界にとどまります。ただし、逆方向では、そのようなスレッドまたはコンテキストの切り替えは発生しません。

したがって、これは予期される動作です。これまでのところ、私が見つけたこの件に関する唯一の (半公式の) 情報源です。

于 2014-03-29T11:16:16.087 に答える