Application.Wait 或 Thread.Sleep

Application.Wait or Thread.Sleep

我已经在单独的线程上使用 backgroundworker.RunAsyn() 到 运行 我的代码。但是,我遇到了代码在上一行完成之前迭代到下一行的部分。我应该创建一个单独的 backgroundworker 来处理吗?或者我应该使用 Application.Wait() 还是 Thread.Sleep() 我不确定要延迟多少时间,我宁愿不让我的程序等待额外的不需要的时间,所以我不确定哪个采取的路线。这是麻烦制造者的片段。

public Form_Main()
{
   InitializeComponent();
   backgroundworker1.WorkerReportsProgress = true;
   backgroundworker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
   backgroundWorker1_ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
}

private void btnOpenRefreshSave_Click()
{
   backgroundWorker1_RunWorkerAsync();
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
   Excel.Application exApp;
   Excel._Workbook exBook;
   Excel._Worksheet exSheet;

   exBook = (Excel._Workbook)(exApp.WOrkbooks.Open("C:\Book1.xlsx")); 
   exSheet = (Excel._Worksheet)(exBook.ActiveSheet);
   //This is the line of code that often times takes a while
   exBook.RefreshAll();
   //end of trouble line
   exBook.SaveAs("C:\Updated_Book1.xlsx");
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{

}

你为什么要延迟一些事情,你不能在它的一个事件上保存你的工作簿,比如 SheetCalculate(在重新计算任何工作表之后或在图表上绘制任何更改的数据之后发生)并设置一些标志在您的代码中并在该事件(或任何更相关的事件)上重置它

问题是因为 RefreshAll 运行正在后台线程上运行。所以基本上你有自己的后台工作人员 运行ning 和另一个你没有预料到的。

refreshAll 的文档说: 将 BackgroundQuery 属性 设置为 true 的对象在后台刷新。

因此,您只需将 属性 设置为 false 即可解决此问题。然后刷新将 运行 在你的背景工作者的上下文中,这就是你的意图。

如果这仍然不起作用,那么您必须重新考虑您的逻辑并寻找刷新完成时触发的某种事件。如果这不存在,那么除了睡眠之外没有其他解决方案,但这根本不是一个好的解决方案,因为你不知道要睡多久。

关于在这里做什么,我想到了一些事情。你可以尝试使用类似于下面的东西

if (Application.CalculationState === xlDone Then
    everything is finished calculating[enter link description here][1]

另一种选择是(正如其他人所建议的那样)更改后台刷新 属性。快速扫描工作簿可以以编程方式为您更改

foreach (Wrksheet ws in workbook.wss)
{
    foreach (QueryTable table in ws.QueryTables)
      table.BackgroundQuery = false;
}
workbook.RefreshAll();