消息过滤器指示应用程序正忙。 (来自HRESULT的异常:0x8001010A(RPC_E_SERVERCALL_RETRYLATER)) [英] The message filter indicated that the application is busy. (Exception from HRESULT: 0x8001010A (RPC_E_SERVERCALL_RETRYLATER))

查看:95
本文介绍了消息过滤器指示应用程序正忙。 (来自HRESULT的异常:0x8001010A(RPC_E_SERVERCALL_RETRYLATER))的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好


我正在尝试开发一个分割功率点幻灯片的应用程序。当所有拆分请求都在队列中并且逐个照顾时,应用程序是稳定的。 当我尝试使其异步并尝试同时运行两个请求时,我收到错误: 
消息过滤器指示应用程序正忙。 (从HRESULT异常:0x8001010A(RPC_E_SERVERCALL_RETRYLATER))


COM对象不支持多线程和提供了一种由微软支持中心所提供(实施在溶液中)一个替代方法&NBSP,但它没运行良好。


如何实现单线程Interop应用程序的并行处理。


 以下是示例代码


  static void Main(string [] args)

        {

            MainAsync()。GetAwaiter()。GetResult();

        }


        static async Task MainAsync()

        {

           试试
            {

                EnvDTE80.DTE2 dte;

                object obj = null;

                System.Type t = null;



                //获取DTE 8.0的ProgID。

                T = System.Type.GetTypeFromProgID(QUOT; VisualStudio.DTE.10.0" ;,

         真);

                //创建IDE的新实例。

                obj = System.Activator.CreateInstance(t,true);

                //将实例转换为DTE2并分配给变量dte。

                dte =(EnvDTE80.DTE2)obj;



                //注册IOleMessageFilter以处理任何线程 

                //错误。

                MessageFilter.Register();

                //显示Visual Studio IDE。

                dte.MainWindow.Activate();



                // =====================================
$
                // ==在此处插入您的自动化代码。==

                // =====================================
$


               等待SplitSlides(@"PptFile1ToSplit");

               等待SplitSlides(@"PptFile2ToSplit");



                dte.Quit();



                MessageFilter.Revoke();



            }¥b $ b            catch(例外情况)

            {

$
                Console.WriteLine(ex.Message);

            }


            Console.Read();

        }¥b $ b        private static async Task SplitSlides(string fileName)

        {

            if(!File.Exists(fileName))

            {

                Console.WriteLine($" File {fileName}不存在",fileName);

            }


           等待Task.Run(()=>

        {

    &NBSP ;    尽量

          {

  &NBSP ;         //数组与路径

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;   List< String> SlideFilesTemp = new List< string>();
$


             //将当前文件复制到临时文件

            string TempFileName = Guid.NewGuid() + QUOT; .PPTX英寸;

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;串TempFilePath = Path.GetDirectoryName(文件名);

            string TempFolder =" D:\\Temp";

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   string TempFileNamePathGlob = Path.Combine(TempFolder,TempFileName);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   File.Copy(fileName,TempFileNamePathGlob);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   Console.WriteLine(" File copied:{0} => {1}",fileName,TempFileNamePathGlob);
$




  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   PpSlideSizeType slideSize = PpSlideSizeType.ppSlideSizeOnScreen;

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   //计算幻灯片数量
  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; Microsoft.Office.Interop.PowerPoint.Application pptApplication =新Microsoft.Office.Interop.PowerPoint.Application();



&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;演示pptPresentationTemp = pptApplication.Presentations.Open(

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP ;&NBSP;&NBSP;&NBSP;&NBSP; TempFileNamePathGlob,

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP ;&NBSP;&NBSP;&NBSP;&NBSP; MsoTriState.msoFalse,

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP ;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; MsoTriState.msoFalse,

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP ;       MsoTriState.msoFalse);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   int _slidesCount = pptPresentationTemp.Slides.Count;

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   slideSize = pptPresentationTemp.PageSetup.SlideSize;

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;列表与LT;字符串> SlideNameDest = GetSlideNames(fileName,_slidesCount);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   pptPresentationTemp.Close();

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   pptApplication.Quit();



$
  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   Console.WriteLine("在演示文稿中计算幻灯片:{0}",_slidesCount);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   pptApplication = new Microsoft.Office.Interop.PowerPoint.Application();

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;  试试
  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   {
$


$
  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   for(int j = 1; j< = _slidesCount; j ++)

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   {

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   int k = j - 1;

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   string slideName = SlideNameDest [k];
$


  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   string slideFileName = Path.GetFileName(slideName);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   string tempSlideFilePath = Path.Combine(TempFolder,slideFileName);



  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;  演示文稿pptPresentationDest = pptApplication.Presentations.Add(MsoTriState.msoFalse);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   pptPresentationDest.PageSetup.SlideSize = slideSize;

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   pptPresentationDest.Slides.InsertFromFile(TempFileNamePathGlob,0,j,j);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   pptPresentationDest.Slides [1] .ApplyTemplate(TempFileNamePathGlob);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   pptPresentationDest.SaveAs(tempSlideFilePath,PpSaveAsFileType.ppSaveAsDefault,MsoTriState.msoTrue);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   pptPresentationDest.Close();

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   Console.WriteLine("完成幻灯片ID的准备演示:{0}",j);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   SlideFilesTemp.Add(tempSlideFilePath);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;  }
$


  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;  }

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   catch(例外)

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   {

$
  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   throw;

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;  }

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   finally

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   {

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   if(pptApplication!= null)

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   pptApplication.Quit();

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;  }



$
  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   //复制并删除所有创建的文件到S3

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   foreach(SlideFilesTemp中的字符串幻灯片)

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   {

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   string FileName = Path.GetFileName(slide);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   string CopyPath = Path.Combine(TempFilePath,FileName);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   File.Copy(slide,CopyPath);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   Console.WriteLine("文件已复制:{0} => {1}",slide,CopyPath);



  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   File.Delete(幻灯片);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   Console.WriteLine(" File deleted:{0}",slide);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;  }
$


  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   Console.WriteLine("所有任务都为文件{0}",fileName完成;)


  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   //删除临时文件

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   File.Delete(TempFileNamePathGlob);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   Console.WriteLine("文件{0}已删除",TempFileNamePathGlob);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;  }

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   catch(例外e)

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   {

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   Console.WriteLine($" Failed to split file {fileName}",fileName);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   // throw;

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;  }

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   finally

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;   {

$
  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;  }

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;  });
$


  &NBSP; &NBSP; &NBSP; }


  &NBSP; &NBSP; &NBSP; private static List< string> GetSlideNames(string fileName,int countOfPages)

  &NBSP; &NBSP; &NBSP; {

$
  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;列表与LT;串GT; slideNames = new List< string>();

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; foreach(var i in Enumerable.Range(0,countOfPages))

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; {

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; var slideName = fileName.Insert(fileName.Length - 5,$" - {i + 1}");

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; slideNames.Add(slideName);

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; }¥b $ b  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; return slideNames;

  &NBSP; &NBSP; &NBSP; }¥b $ b  &NBSP; }


  &NBSP;公共类MessageFilter:IOleMessageFilter

  &NBSP; {

  &NBSP; &NBSP; &NBSP; //

  &NBSP; &NBSP; &NBSP; //包含IOleMessageFilter的类

  &NBSP; &NBSP; &NBSP; //线程错误处理功能。



  &NBSP; &NBSP; &NBSP; //启动过滤器。

  &NBSP; &NBSP; &NBSP; public static void Register()

  &NBSP; &NBSP; &NBSP; {

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; IOleMessageFilter newFilter = new MessageFilter();

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; IOleMessageFilter oldFilter = null;

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; CoRegisterMessageFilter(newFilter,out oldFilter);

  &NBSP; &NBSP; &NBSP; }


  &NBSP; &NBSP; &NBSP; //完成过滤器,关闭它。

  &NBSP; &NBSP; &NBSP; public static void Revoke()

  &NBSP; &NBSP; &NBSP; {

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; IOleMessageFilter oldFilter = null;

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; CoRegisterMessageFilter(null,out oldFilter);

  &NBSP; &NBSP; &NBSP; }


  &NBSP; &NBSP; &NBSP; //

  &NBSP; &NBSP; &NBSP; // IOleMessageFilter函数。

  &NBSP; &NBSP; &NBSP; //处理传入的线程请求。

  &NBSP; &NBSP; &NBSP; INT IOleMessageFilter.HandleInComingCall(INT dwCallType,

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; System.IntPtr hTaskCaller,INT dwTickCount,System.IntPtr

&NBSP;&NBSP;&NBSP ;   lpInterfaceInfo)

  &NBSP; &NBSP; &NBSP; {

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; //返回标志SERVERCALL_ISHANDLED。

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;返回0;

  &NBSP; &NBSP; &NBSP; }


  &NBSP; &NBSP; &NBSP; //线程通话被拒绝了,请再试一次。

  &NBSP; &NBSP; &NBSP; INT IOleMessageFilter.RetryRejectedCall(System.IntPtr

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; hTaskCallee,INT dwTickCount,INT dwRejectType)

&NBSP; &NBSP; &NBSP; &NBSP; {

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; if(dwRejectType == 2)

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; // flag = SERVERCALL_RETRYLATER。

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; {

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; //如果返回> = 0& 

 请立即重试线程调用&NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; //< 100。

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;返回99;

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; }¥b $ b  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; // 太忙了;取消通话。

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;返回-1;

  &NBSP; &NBSP; &NBSP; }


  &NBSP; &NBSP; &NBSP; INT IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee,

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; INT dwTickCount,INT dwPendingType)

&NBSP; &NBSP; &NBSP; &NBSP; {

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP; //返回标志PENDINGMSG_WAITDEFPROCESS。

  &NBSP; &NBSP; &NBSP; &NBSP; &NBSP;返回2;

  &NBSP; &NBSP; &NBSP; }


  &NBSP; &NBSP; &NBSP; //实现IOleMessageFilter接口。

  &NBSP; &NBSP; &NBSP; [DllImport(" Ole32.dll")]
$
  &NBSP; &NBSP; &NBSP; private static extern int

  &NBSP; &NBSP; &NBSP; &NBSP; CoRegisterMessageFilter(IOleMessageFilter newFilter,出

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; IOleMessageFilter oldFilter);

&NBSP; &NBSP; }


  &NBSP; [ComImport(),Guid(" 00000016-0000-0000-C000-000000000046"),zh
  &NBSP; InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]

  &NBSP; interface IOleMessageFilter

  &NBSP; {

  &NBSP; &NBSP; &NBSP; [PreserveSig]

  &NBSP; &NBSP; &NBSP; INT HandleInComingCall(

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; INT dwCallType,

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; IntPtr的hTaskCaller,

       int dwTickCount,

       IntPtr lpInterfaceInfo);



  &NBSP; &NBSP; &NBSP; [PreserveSig]

  &NBSP; &NBSP; &NBSP; INT RetryRejectedCall(

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; IntPtr的hTaskCallee,

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;诠释dwTickCount,

       int dwRejectType);
$


  &NBSP; &NBSP; &NBSP; [PreserveSig]

  &NBSP; &NBSP; &NBSP; int MessagePending(

       IntPtr hTaskCallee,

       int dwTickCount,

       int dwPendingType);

  &NBSP; }




谢谢

解决方案

您好,


如果您只处理开放XML文档,可以考虑使用Open XML SDK。请参阅欢迎使用Open XML SDK 2.5 for Office  欲了解更多信息。 


Office对象模型不是线程安全的。我 n
在Visual Studio中使用Office开发工具创建的解决方案的情况下,COM互操作将所有被拒绝的调用转换为 
系统.Runtime.InteropServices.COMException  ("
消息过滤器指示应用程序正忙")。每当您在后台线程上进行对象模型调用时,您必须准备好处理此异常。通常,这涉及重试一段时间,然后在对话框中显示
。但是,您也可以将后台线程创建为STA,然后为该线程注册消息过滤器以处理此情况。在线程
Office支持
中详细了解相关内容&NBSP;文章


Hi

I am trying to develop an application to split power point slides. Application is stable when there all split requests are in queue and catered one by one.  When I try to make it async and tried to run two requests simultaneously I am getting error: The message filter indicated that the application is busy. (Exception from HRESULT: 0x8001010A (RPC_E_SERVERCALL_RETRYLATER))

COM object does not support multi-threading and there is a workaround provided provided by Microsoft Help Center (Implemented in solution) but it didn't work well.

How can I achieve parallel processing for single threaded Interop applications.

 Here is sample Code

  static void Main(string[] args)
        {
            MainAsync().GetAwaiter().GetResult();
        }

        static async Task MainAsync()
        {
            try
            {
                EnvDTE80.DTE2 dte;
                object obj = null;
                System.Type t = null;

                // Get the ProgID for DTE 8.0.
                t = System.Type.GetTypeFromProgID("VisualStudio.DTE.10.0",
                  true);
                // Create a new instance of the IDE.
                obj = System.Activator.CreateInstance(t, true);
                // Cast the instance to DTE2 and assign to variable dte.
                dte = (EnvDTE80.DTE2)obj;

                // Register the IOleMessageFilter to handle any threading 
                // errors.
                MessageFilter.Register();
                // Display the Visual Studio IDE.
                dte.MainWindow.Activate();

                // =====================================
                // ==Insert your automation code here.==
                // =====================================

                await SplitSlides(@"PptFile1ToSplit");
                await SplitSlides(@"PptFile2ToSplit");

                dte.Quit();

                MessageFilter.Revoke();

            }
            catch (Exception ex)
            {

                Console.WriteLine(ex.Message);
            }

            Console.Read();
        }
        private static async Task SplitSlides(string fileName)
        {
            if (!File.Exists(fileName))
            {
                Console.WriteLine($"File {fileName} does not exist", fileName);
            }

            await Task.Run(() =>
             {
                 try
                 {
                     // Array with path
                     List<String> SlideFilesTemp = new List<string>();

                     // Copy current file to temporary file
                     string TempFileName = Guid.NewGuid() + ".pptx";
                     string TempFilePath = Path.GetDirectoryName(fileName);
                     string TempFolder = "D:\\Temp";
                     string TempFileNamePathGlob = Path.Combine(TempFolder, TempFileName);
                     File.Copy(fileName, TempFileNamePathGlob);
                     Console.WriteLine("File copied : {0} => {1}", fileName, TempFileNamePathGlob);


                     PpSlideSizeType slideSize = PpSlideSizeType.ppSlideSizeOnScreen;
                     //Count Number of Slides
                     Microsoft.Office.Interop.PowerPoint.Application pptApplication = new Microsoft.Office.Interop.PowerPoint.Application();

                     Presentation pptPresentationTemp = pptApplication.Presentations.Open(
                                       TempFileNamePathGlob,
                                       MsoTriState.msoFalse,
                                       MsoTriState.msoFalse,
                                       MsoTriState.msoFalse);
                     int _slidesCount = pptPresentationTemp.Slides.Count;
                     slideSize = pptPresentationTemp.PageSetup.SlideSize;
                     List<String> SlideNameDest = GetSlideNames(fileName, _slidesCount);
                     pptPresentationTemp.Close();
                     pptApplication.Quit();


                     Console.WriteLine("Count slides in presentation : {0}", _slidesCount);
                     pptApplication = new Microsoft.Office.Interop.PowerPoint.Application();
                     try
                     {


                         for (int j = 1; j <= _slidesCount; j++)
                         {
                             int k = j - 1;
                             string slideName = SlideNameDest[k];

                             string slideFileName = Path.GetFileName(slideName);
                             string tempSlideFilePath = Path.Combine(TempFolder, slideFileName);

                             Presentation pptPresentationDest = pptApplication.Presentations.Add(MsoTriState.msoFalse);
                             pptPresentationDest.PageSetup.SlideSize = slideSize;
                             pptPresentationDest.Slides.InsertFromFile(TempFileNamePathGlob, 0, j, j);
                             pptPresentationDest.Slides[1].ApplyTemplate(TempFileNamePathGlob);
                             pptPresentationDest.SaveAs(tempSlideFilePath, PpSaveAsFileType.ppSaveAsDefault, MsoTriState.msoTrue);
                             pptPresentationDest.Close();
                             Console.WriteLine("Done prepare presentation for slide ID : {0}", j);
                             SlideFilesTemp.Add(tempSlideFilePath);
                         }

                     }
                     catch (Exception)
                     {

                         throw;
                     }
                     finally
                     {
                         if (pptApplication != null)
                             pptApplication.Quit();
                     }


                     // Copy and remove all created files to S3
                     foreach (string slide in SlideFilesTemp)
                     {
                         string FileName = Path.GetFileName(slide);
                         string CopyPath = Path.Combine(TempFilePath, FileName);
                         File.Copy(slide, CopyPath);
                         Console.WriteLine("File copied : {0} => {1}", slide, CopyPath);

                         File.Delete(slide);
                         Console.WriteLine("File deleted : {0}", slide);
                     }

                     Console.WriteLine("All tasks are done for file {0}", fileName);

                     // Remove temporary file
                     File.Delete(TempFileNamePathGlob);
                     Console.WriteLine("File {0} was removed", TempFileNamePathGlob);
                 }
                 catch (Exception e)
                 {
                     Console.WriteLine($"Failed to split file {fileName}", fileName);
                     //throw;
                 }
                 finally
                 {

                 }
             });

        }

        private static List<string> GetSlideNames(string fileName, int countOfPages)
        {

            List<string> slideNames = new List<string>();
            foreach (var i in Enumerable.Range(0, countOfPages))
            {
                var slideName = fileName.Insert(fileName.Length - 5, $"-{i + 1}");
                slideNames.Add(slideName);
            }
            return slideNames;
        }
    }

    public class MessageFilter : IOleMessageFilter
    {
        //
        // Class containing the IOleMessageFilter
        // thread error-handling functions.

        // Start the filter.
        public static void Register()
        {
            IOleMessageFilter newFilter = new MessageFilter();
            IOleMessageFilter oldFilter = null;
            CoRegisterMessageFilter(newFilter, out oldFilter);
        }

        // Done with the filter, close it.
        public static void Revoke()
        {
            IOleMessageFilter oldFilter = null;
            CoRegisterMessageFilter(null, out oldFilter);
        }

        //
        // IOleMessageFilter functions.
        // Handle incoming thread requests.
        int IOleMessageFilter.HandleInComingCall(int dwCallType,
          System.IntPtr hTaskCaller, int dwTickCount, System.IntPtr
          lpInterfaceInfo)
        {
            //Return the flag SERVERCALL_ISHANDLED.
            return 0;
        }

        // Thread call was rejected, so try again.
        int IOleMessageFilter.RetryRejectedCall(System.IntPtr
          hTaskCallee, int dwTickCount, int dwRejectType)
        {
            if (dwRejectType == 2)
            // flag = SERVERCALL_RETRYLATER.
            {
                // Retry the thread call immediately if return >=0 & 
                // <100.
                return 99;
            }
            // Too busy; cancel call.
            return -1;
        }

        int IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee,
          int dwTickCount, int dwPendingType)
        {
            //Return the flag PENDINGMSG_WAITDEFPROCESS.
            return 2;
        }

        // Implement the IOleMessageFilter interface.
        [DllImport("Ole32.dll")]
        private static extern int
          CoRegisterMessageFilter(IOleMessageFilter newFilter, out
          IOleMessageFilter oldFilter);
    }

    [ComImport(), Guid("00000016-0000-0000-C000-000000000046"),
    InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    interface IOleMessageFilter
    {
        [PreserveSig]
        int HandleInComingCall(
            int dwCallType,
            IntPtr hTaskCaller,
            int dwTickCount,
            IntPtr lpInterfaceInfo);

        [PreserveSig]
        int RetryRejectedCall(
            IntPtr hTaskCallee,
            int dwTickCount,
            int dwRejectType);

        [PreserveSig]
        int MessagePending(
            IntPtr hTaskCallee,
            int dwTickCount,
            int dwPendingType);
    }

Thanks

解决方案

Hello,

You may consider using the Open XML SDK if you deal with open XML documents only. See Welcome to the Open XML SDK 2.5 for Office for more information. 

The Office object model is not thread safe. In the case of solutions created by using the Office development tools in Visual Studio, COM interop converts all rejected calls to a System.Runtime.InteropServices.COMException ("The message filter indicated that the application is busy"). Whenever you make an object model call on a background thread, you must to be prepared to handle this exception. Typically, that involves retrying for a certain amount of time and then displaying a dialog. However, you can also create the background thread as STA and then register a message filter for that thread to handle this case. Read more about that in the Threading Support in Office article.


这篇关于消息过滤器指示应用程序正忙。 (来自HRESULT的异常:0x8001010A(RPC_E_SERVERCALL_RETRYLATER))的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆