0

Outlook-2010アドインを開発しています。

Mainアドインクラスは、次のような非同期タスクを起動し、他のフォームからサブスクライブする静的イベントを宣言しています。

        int ProcesadosArchivado = 0;
        public delegate void OnFileArchivedDelegate (int NumFilesArchived, string NameArchived);
        public static event OnFileArchivedDelegate OnFileArchivedEvent = delegate { };


        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {   
            Thread hiloArchivado = new Thread(DoArchiveBackground);
            hiloArchivado.Start();

        }       

       private void DoArchiveBackground()
       {

            try
            {           
                Outlook.Application app = null;
                Outlook._NameSpace ns = null;
                Outlook.MailItem item = null;
                //Outlook.MAPIFolder inboxFolder = null;
                DateTime MyDateTime = DateTime.Now.AddMonths(-3);
                app = new Outlook.Application();
                ns = app.GetNamespace("MAPI");
                ns.Logon(null, null, false, false);    

                Outlook.Stores store;
                Outlook.MAPIFolder rootFolder = null;
                store = Application.Session.Stores;
                foreach (Outlook.Store storeClass in store.Session.Stores)
                {
                    rootFolder = storeClass.GetRootFolder();    
                }    

                Outlook.MAPIFolder folder = rootFolder.Folders["ARCHIVAR"];    
                Outlook.MAPIFolder ArchivarFolder = ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);  

                // inboxFolder = ns.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);


                for (int i = 1; i <= ArchivarFolder.Items.Count; i++)
                {
                    try
                    {

                      item = (Microsoft.Office.Interop.Outlook.MailItem)ArchivarFolder.Items[i];
                      ProcesadosArchivado += 1;
                      OnFileArchivedDelegate myEvent = OnFileArchivedEvent;
                      myEvent.Invoke(ProcesadosArchivado, item.Subject);                          


                    //Messate iteration
                    }
                    catch (Exception ex)
                    {

                        throw;
                    }

                }

            }

            //Catch folder iteration
            catch (Exception ex)
            {

                throw;
            }

        }

次に、他のフォームから静的イベントをサブスクライブし、InvokeRequiredとデリゲートを使用していくつかのコントロールを更新しようとします。

  public partial class ArchiveForm : Form
    {
        private  delegate void UpdateControlDelegate (Control control,string Property,string value);

        public ArchiveForm()
        {
            InitializeComponent();
            this.Load += new EventHandler(ArchiveForm_Load);
        }



        void ArchiveForm_Load(object sender, EventArgs e)
        {
            ThisAddIn.OnFileArchivedEvent += new ThisAddIn.OnFileArchivedDelegate(ThisAddIn_OnFileArchivedEvent);
        }

        void ThisAddIn_OnFileArchivedEvent(int NumFilesArchived, string NameArchived)
        {
            updateControls(NumFilesArchived,NameArchived);         

        }

        void UpdateControl(Control control,string Property,string value)
        {
            PropertyInfo prop = control.GetType().GetProperty("Text");

            prop.SetValue(control, 
                        Convert.ChangeType(value, prop.PropertyType), null);         

        }

  private void updateControls(int NumFilesArchived, string NameArchived)
  {            

            if (lblArchivado.InvokeRequired)
            {
                UpdateControlDelegate del = new UpdateControlDelegate(UpdateControl);
                //del.BeginInvoke(lblArchivado, "Text", "Archivados: " + NumFilesArchived.ToString(), null, null);
                del.Invoke(lblArchivado, "Text", "Archivados: " + NumFilesArchived.ToString());
            }
            else
                this.lblArchivado.Text = "Archivados: " + NumFilesArchived.ToString();

            if (lblAsunto.InvokeRequired)
            {
                UpdateControlDelegate del = new UpdateControlDelegate(UpdateControl);
                //del.BeginInvoke(lblAsunto, "Text", "Asunto: " + NameArchived, null, null);
                del.Invoke(lblAsunto, "Text", "Asunto: " + NameArchived);
            }

            else
                this.lblAsunto.Text = "Asunto: " + NameArchived;

        }


    }

行に到達したときにCross-HeadInvalid操作例外が発生します:

* prop.SetValue(control、Convert.ChangeType(value、prop.PropertyType)、null); *

invoreRequiredを通過し、デリゲートを呼び出しているので、この例外が発生する理由がわかりません。

4

2 に答える 2

0

さて、いくつかの調査を行った後、私はこれを変更しました:

del.Invoke(lblAsunto, "Text", "Asunto: " + NameArchived);

これに:

this.Invoke(del, new object[] { lblAsunto, "Text", "Asunto: " + NameArchived });

そして、それは現在機能しています。

于 2013-02-13T10:39:49.640 に答える
0

セカンダリスレッドからOutlookオブジェクトモデルを使用しないでください。それは問題を引き起こすに違いありません。Outlook 2013は、OOMオブジェクトがそれを返したスレッドとは異なるスレッドからアクセスされた場合、すぐに例外を発生させます。古いバージョンのOutlook migthはほとんどの場合機能しますが、最も残念な瞬間に失敗します。
上記のコードは、セカンダリスレッドにOutlook.Applicationオブジェクトの新しいインスタンスを作成します。それは可能ですが、すべての呼び出しがOutlookのメインスレッドにマーシャリングされるため、セカンダリスレッドを使用してもあまり効果はありません。
唯一の回避策は、Extended MAPi(C ++またはDelphi)を使用するか、内部でMAPIを使用するラッパー(Redemptionなど)を使用することです。

于 2013-02-13T15:42:54.957 に答える