c# Excel互操作-如何测试互操作对象是否仍在工作并执行任务



我正在循环通过几百个excel文件的目录,并试图刷新excel文件一次一个。我一直得到这个错误,这表明刷新操作仍在文件A上运行,例如,FileB正在尝试启动刷新操作。循环速度太快了,不知怎么的,我必须等待文件A的先前刷新操作完成后才能开始刷新文件b。

未处理的异常:System.Runtime.InteropServices.COMException: The消息过滤器指示应用程序正忙。(例外HRESULT: 0x8001010A (rpce_servercall_retrylater)) atMicrosoft.Office.Interop.Excel._Workbook.RefreshAll ()RefreshExcelFiles.Program。RefreshFile(字符串文件名)

这是我的代码。在循环中开始处理新文件之前,如何等待刷新操作完成?或者,在开始处理新文件之前,等待wb对象上的封送释放操作完成?
using System;
using System.Configuration;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Excel;
namespace RefreshExcelFiles
{
    internal class Program
    {
        private static string _fileDirectory;
        private static Application _excelApp;
        private static void Main(string[] args)
        {
            _fileDirectory = ConfigurationManager.AppSettings["FileDirectory"];
            _excelApp = new Application();
            _excelApp.DisplayAlerts = false;
            Console.WriteLine("starting to refresh files");
            int i = 0;
            int total = Directory.GetFiles(_fileDirectory).Length;
            foreach (string file in Directory.GetFiles(_fileDirectory))
            {
                i += 1;
                Console.WriteLine("File " + file + " " + i.ToString() + "/" + total.ToString());
                RefreshFile(file);
            }
            _excelApp.Quit();
            Marshal.FinalReleaseComObject(_excelApp);
            Console.WriteLine("press any key to exit");
            Console.ReadLine();
        }
        private static void RefreshFile(string fileName)
        {
            _Workbook wb = _excelApp.Workbooks.Open(fileName, false);
            wb.RefreshAll();
            wb.Save();
            wb.Close(Type.Missing, Type.Missing, Type.Missing);
            Marshal.FinalReleaseComObject(wb);
        }
    }
}

我找到了解决问题的办法。我需要实现IMessageFilter RetryRejectedCall。用于c#和VB。使用IMessageFilter::RetryRejectedCall的。NET代码示例,参见此博客文章(wayback机器存档链接)。

如果你不注册一个MessageFilter自己(通过调用CoRegisterMessageFilter),你会得到默认的行为,这将是失败的调用,如果它. net将失败HRESULT转换为异常。当您尝试呼叫时,要处理服务器忙的可能性,您需要在客户端代码中实现IMessageFilter::RetryRejectedCall,并注册消息过滤器。在大多数情况下,您只需要等待几秒钟,然后重试调用——通常这将是足够的时间使Word完成它正在做的事情,以便它可以处理你的呼叫。

最新更新