背景
我在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;
}
}
答案 0 :(得分:0)
我能够通过以下方式实现这一目标。自定义表单有一个进度条,其样式设置为选框。
我从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不建议在单独的线程上使用对象模型。