.net - Excel file operations using interop in multithreaded C# application fails -


i've application automates file related jobs. every job executed inside separate threads. 1 kind of job exporting excel file html format. use microsoft.office.interop.excel namespace purpose. application working fine under windows server 2008 environment upgraded our server windows server 2012 , started following error :

the message filter indicated application busy. (exception hresult: 0x8001010a (rpc_e_servercall_retrylater))

the thing first call export function exports excel file html successive calls fails above error. make sure close , finalize excel related objects , check task manager excel.exe not working no luck.

i use following code retry if error occurs keeps getting exception , fails after 5 retries

while (!success)             { try                 {                     exportexcel();                     success = true;                     system.threading.thread.sleep(2000);                 }                 catch (system.runtime.interopservices.comexception loe)                 {                     trycount++;                     if (loe.hresult.tostring("x") == "80010001" || loe.hresult.tostring("x") == "8001010a" && trycount<5)                     {                                                                                            system.threading.thread.sleep(2000);                     }                     else                     {                         throw;                     }                 }              } 

i suspect might related threading error can't come answer. insight helpful.

thank joe pointing out right way:

i ended using solution mixture of following links: http://blogs.artinsoft.net/mrojas/archive/2012/09/28/office-interop-and-call-was-rejected-by-callee.aspx

http://blogs.msdn.com/b/pfxteam/archive/2010/04/07/9990421.aspx

so used following:

stataskscheduler cts=new stataskscheduler(1); taskfactory factory;           factory = new taskfactory(cts); task jobruntask = factory.startnew(() => {    messagefilter.register();    excelinteropfunction();    messagefilter.revove();  }); 

i believe excel object model apartment threaded, calls multiple threads marshaled same thread in excel process - may busy if there several client threads.

you can implement imessagefilter (ole message filter, not confused system.windows.forms.imessagefilter) provide custom retry logic.

your server upgrade might have changed timing characteristics problem occurs more frequently.

update

here sample basic implementation of ole message filter:

    // definition of imessagefilter interface need implement ,      // register coregistermessagefilter api.     [comimport(), guid("00000016-0000-0000-c000-000000000046"), interfacetypeattribute(cominterfacetype.interfaceisiunknown)]     interface iolemessagefilter // renamed avoid confusion w/ system.windows.forms.imessagefilter     {         [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);     }      internal sealed class olemessagefilter : iolemessagefilter, idisposable     {         [dllimport("ole32.dll")]         private static extern int coregistermessagefilter(iolemessagefilter newfilter, out iolemessagefilter oldfilter);          private bool _isregistered;         private iolemessagefilter _oldfilter;          public olemessagefilter()         {             register();         }          private void register()         {             // coregistermessagefilter supported on sta thread.  throw exception             // if can't switch sta             thread.currentthread.setapartmentstate(apartmentstate.sta);              int result = coregistermessagefilter(this, out _oldfilter);             if (result != 0)             {                 throw new comexception("coregistermessagefilter failed", result);             }             _isregistered = true;         }          private void revoke()         {             if (_isregistered)             {                 iolemessagefilter revokedfilter;                 coregistermessagefilter(_oldfilter, out revokedfilter);                 _oldfilter = null;                 _isregistered = false;             }         }          #region idisposable members          private void dispose(bool disposing)         {             if (disposing)             {                 // dispose managed resources             }             // dispose unmanaged resources             revoke();         }          void idisposable.dispose()         {             gc.suppressfinalize(this);             dispose(true);         }          ~olemessagefilter()         {             dispose(false);         }          #endregion          #region iolemessagefilter members          int iolemessagefilter.handleincomingcall(int dwcalltype, intptr htaskcaller, int dwtickcount, intptr lpinterfaceinfo)         {             return 0; //servercall_ishandled         }          int iolemessagefilter.retryrejectedcall(intptr htaskcallee, int dwtickcount, int dwrejecttype)         {             if (dwrejecttype == 2) // servercall_retrylater             {                 return 200; // wait 200ms , try again             }              return -1; // cancel call         }          int iolemessagefilter.messagepending(intptr htaskcallee, int dwtickcount, int dwpendingtype)         {             return 2; //pendingmsg_waitdefprocess         }         #endregion     } 

you can @ this sample, though displays prompt asking user if want retry, not appropriate if client multithreaded , server-based.


Comments

Popular posts from this blog

angularjs - ADAL JS Angular- WebAPI add a new role claim to the token -

php - CakePHP HttpSockets send array of paramms -

node.js - Using Node without global install -