简体   繁体   中英

Application.Wait or Thread.Sleep

I am already using backgroundworker.RunAsyn() to run my code on a separate thread. However I am hitting a portion where the code iterates to the next line before the previous line is completed. Should I create a separate backgroundworker to handle that? Or should I use Application.Wait() or Thread.Sleep() I am not sure the amount of time to delay and I'd rather not have my program just sitting around waiting for extra un-needed time so I am not sure which route to take. Here is a snippet of the trouble-maker.

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)
{

}

The problem is caused because RefreshAll is running on a background thread. So basically you have your own backgroundworker running and another one you did not anticipate for.

The documentation for refreshAll says : Objects that have the BackgroundQuery property set to true are refreshed in the background.

So you can get out of this problem only be setting that property to false. Then the refreshall would run in the context of your backgroundworker which is what your intent is.

If this still does not work, then you have to rethink your logic and look for an event of some kind that is triggered when the refresh is done. If this does not exist, then there is no solution other than a sleep, but that is not a good solution at all because you don't know how long to sleep.

A few things come to mind on what to do here. You could try using something similar to the below

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

Another option would be (as others have suggested) changing the background refresh property. A quick scan of the workbooks could programmatically change that for you

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM