2

背景:

我在 Outlook 加载项中使用一个简单的进度对话框来显示执行长时间操作的进度。由于我无法在单独的线程中运行使用 Outlook 对象的代码,因此我无法实现更传统的后台工作进程。我的加载项一直工作正常,直到 Outlook 2013 在某些情况下我的进度对话框挂起。当我在 VS 调试器中运行加载项并导致挂起,然后中断时,它似乎卡在尝试强制更新进度条的 DoEvents() 行上。

我的问题:

有人可以建议一个更好的系统来显示上述限制的进展(长时间运行的代码必须在主 Outlook 线程中运行)。有没有更好的方法可以在不使用 DoEvents() 的情况下使进度对话框响应?

下面的简单代码演示了我现在是如何做到这一点的。在对 Outlook 对象执行长操作的加载项代码中:

private void longRunningProcess()
{
    int max = 100;

    DlgStatus dlgstatus = new DlgStatus();
    dlgstatus.ProgressMax = max;
    dlgstatus.Show();

    for (int i = 0; i < max; i++)
    {
        //Execute long running code that MUST best run in the main (Outlook's) thread of execution...
        System.Threading.Thread.Sleep(1000); //for simulation purposes

        if (dlgstatus.Cancelled) break;
        dlgstatus.SetProgress("Processing item: " + i.ToString(), i);
    }
}

这是简单进度对话框窗口的代码:

public partial class DlgStatus : Form
{
    private bool _cancelled;

    public DlgStatus()
    {
        InitializeComponent();
    }

    public int ProgressMax
    {
        set 
        {
            progress.Maximum = value;
            Application.DoEvents();
        }
    }

    public bool Cancelled
    {
        get { return _cancelled; }
    }

    public void SetProgress(string status, int val)
    {
        lblStatus.Text = status;
        progress.Value = val;
        Application.DoEvents();  //Seems to hang here
    }

    private void btnCancel_Click(object sender, EventArgs e)
    {
        _cancelled = true;
        Application.DoEvents();
        this.Visible = false;
    }
}
4

1 回答 1

0

通过执行以下操作,我能够做到这一点。自定义表单有一个进度条,其样式设置为 Marquee。

我从http://social.msdn.microsoft.com/Forums/en/vsto/thread/59993421-cbb5-4b7b-b6ff-8a28f74a1fe5获得了通用方法,但发现我不需要使用所有自定义窗口句柄。

private void btn_syncContacts_Click(object sender, RibbonControlEventArgs e)
{
     Thread t = new Thread(SplashScreenProc);
     t.Start();

     //long running code
     this.SyncContacts();

     syncingSplash.Invoke(new Action(this.syncingSplash.Close), null);
}

private SyncingContactsForm syncingSplash = new SyncingContactsForm();

internal void SplashScreenProc(object param)
{
    this.syncingSplash.ShowDialog();
}

请务必注意,该表单不适用于 Outlook 对象模型。Microsoft 不建议在单独的线程上使用对象模型。

于 2013-01-28T14:36:26.663 回答