Answered by:
SyncOrchestrator w/Proxy Throws Exception When Too Many Updates

Question
-
Originally, I modified the DatabaseSyncSQLandSQLCompact example (found at http://code.msdn.microsoft.com/Release/ProjectReleases.aspx?ProjectName=sync&ReleaseId=3422) to sync between SQL2008 and SQLEXPRESS(2005 or 2008). This worked fine. I can add, for example, 2000 records, no problems.
Similarly, I modified the SDK example WebSharingAppDemo-CEProviderEndToEnd (which uses WCF) to use SQLEXPRESS instead of SQLCE. I have got it working for a local service hosted in VS2008 as well as a remote service running on W2003 w/IIS6.0. Well, that is, as long as the changes are not too many. I can successfully do 500 adds total to orders and orders_detail tables.
If I do 2000 adds to the server database and then have the client as the source provider and the server as the destination provider (the proxy), direction to source (same as all above tests), then I get an exception thrown by SyncOrchestrator on this statement in SynchronizationHelper.cs, method SynchronizeProviders():
SyncOperationStatistics stats = orchestrator.Synchronize();
The exception is:
System.InvalidCastException was unhandled
Message="Unable to cast COM object of type 'System.__ComObject' to interface type 'ISyncKnowledge2'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{ED0ADDC0-3B4B-46A1-9A45-45661D2114C8}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE))."
Source="Microsoft.Synchronization"
StackTrace:
Server stack trace:
at System.ServiceModel.Channels.CommunicationObject.ThrowPending()
at System.ServiceModel.Channels.CommunicationObject.ThrowIfDisposedOrNotOpen()
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at SqlSyncService.IRelationalSyncContract.EndSession()
at SqlSyncService.RelationalProviderProxy.EndSession(SyncSessionContext syncSessionContext) in <removed for my privacy>\RelationalProviderProxy.cs:line 73
at Microsoft.Synchronization.KnowledgeProviderProxy.EndSession(ISyncSessionState pSessionState)
at Microsoft.Synchronization.CoreInterop.ISyncSession.Start(CONFLICT_RESOLUTION_POLICY resolutionPolicy, _SYNC_SESSION_STATISTICS& pSyncSessionStatistics)
at Microsoft.Synchronization.KnowledgeSyncOrchestrator.DoOneWaySyncHelper(SyncIdFormatGroup sourceIdFormats, SyncIdFormatGroup destinationIdFormats, KnowledgeSyncProviderConfiguration destinationConfiguration, SyncCallbacks DestinationCallbacks, ISyncProvider sourceProxy, ISyncProvider destinationProxy, ChangeDataAdapter callbackChangeDataAdapter, SyncDataConverter conflictDataConverter, Int32& changesApplied, Int32& changesFailed)
at Microsoft.Synchronization.KnowledgeSyncOrchestrator.DoOneWayKnowledgeSync(SyncDataConverter sourceConverter, SyncDataConverter destinationConverter, SyncProvider sourceProvider, SyncProvider destinationProvider, Int32& changesApplied, Int32& changesFailed)
at Microsoft.Synchronization.KnowledgeSyncOrchestrator.Synchronize()
at Microsoft.Synchronization.SyncOrchestrator.Synchronize()
at SyncApplication.SynchronizationHelper.SynchronizeProviders(RelationalSyncProvider localProvider, RelationalProviderProxy remoteProvider, SyncDirectionOrder direction) in <removed for my privacy>\app\SynchronizationHelper.cs:line 48
at SyncApplication.ExpressSharingForm.synchronizeBtn_Click(Object sender, EventArgs e) in <removed for my privacy>\app\ClientSharingForm.cs:line 239
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at SyncApplication.OfflineApp.Main() in <removed for my privacy>\SharingApp.cs:line 24
InnerException:
I did a search for ISyncKnowledge2 on the web and all I find is a couple of references to it in the release notes for SyncFx 2.0 release notes.
Application is running on Vista SP1, VS2008, Framework 3.5 SP1, SyncFx 2.0 (RTM? - it's the most recent version).
Anybody have any ideas on what sort of sizing violation might be causing this?
TIA
Steve- Moved by Liam Cavanagh - MSFTMicrosoft employee Thursday, January 21, 2010 4:37 PM (From:SyncFx - General)
Monday, January 18, 2010 7:03 PM
Answers
-
Hi,
I assume that you didn't see this COM exception with the original sample for the same batching setting and the number of records. There is a new MSDN sample for syncing SQL Server and SQL Express: http://code.msdn.microsoft.com/Release/ProjectReleases.aspx?ProjectName=sync&ReleaseId=3762. Instead of modifying the SQL Server with SQLCE sample, can you use new sample instead? Let us know if you get same repro with the new sample still.
For the COM exception, I don't know how you modified the original sample. Did you change it to a MTA application? The original sample is a UI app and run as STA. If you ran your sync in different thread with mismatch thread apartment model, you will hit this COM exception as you has found out.
Also, did you enable Reliable Messaging in your changes? In this case, you need to create your provider and start sync in a MTA thread if your app is not MTA.
Thanks,
Dong
This posting is provided AS IS with no warranties, and confers no rights.- Proposed as answer by Dong CaoMicrosoft employee Saturday, January 30, 2010 2:15 AM
- Marked as answer by Dong CaoMicrosoft employee Tuesday, February 2, 2010 6:28 PM
- Unmarked as answer by Speedware Saturday, March 13, 2010 4:52 AM
- Marked as answer by Speedware Monday, March 15, 2010 1:40 PM
Saturday, January 30, 2010 2:15 AM
All replies
-
I found the information below in the MSF help file. Is this related? I can see the interface IID is different, but I am wondering if the error above is the same thing.
I'm wondering if this has something to do with the fact that the sample WebSharingAppDemo-CEProviderEndToEnd has the main form application (from where the synchronization is initiated) as well as the webservice running. Are these separate threads within the same process and does that cause this?
You see, the original application that I modified (WebSharingAppDemo-CEProviderEndToEnd) has the SqlCeSyncProvider provider which I suspect means stuff for that provider is executed inline whereas I changed it to use SqlSyncProvider which I am guessing is not.
Any help would be greatly appreciated.
Managed Application Throws System.Runtime.InteropServices.COMException (0x80004002)
A managed synchronization application throws System.Runtime.InteropServices.COMException with the following error message: "Unable to cast COM object of type 'Sync Framework Managed Class' to interface type 'Sync Framework COM Interop Class'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{73EA794F-1251-4466-A19C-DAEAF5BDBD04}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE))."
This exception occurs when a Sync Framework object is created in one single-threaded apartment and a method of the object is called from a different single-threaded apartment. In this case, the .NET Framework tries to marshal the Sync Framework object from one apartment to the other by querying the Sync Framework object for the IMarshal interface. Sync Framework objects do not implement IMarshal and so the call fails with this exception.
Solution
Use multithreaded apartment (MTA) threads. Marshaling is not required for MTA threads.Friday, January 22, 2010 6:12 AM -
Hi,
I assume that you didn't see this COM exception with the original sample for the same batching setting and the number of records. There is a new MSDN sample for syncing SQL Server and SQL Express: http://code.msdn.microsoft.com/Release/ProjectReleases.aspx?ProjectName=sync&ReleaseId=3762. Instead of modifying the SQL Server with SQLCE sample, can you use new sample instead? Let us know if you get same repro with the new sample still.
For the COM exception, I don't know how you modified the original sample. Did you change it to a MTA application? The original sample is a UI app and run as STA. If you ran your sync in different thread with mismatch thread apartment model, you will hit this COM exception as you has found out.
Also, did you enable Reliable Messaging in your changes? In this case, you need to create your provider and start sync in a MTA thread if your app is not MTA.
Thanks,
Dong
This posting is provided AS IS with no warranties, and confers no rights.- Proposed as answer by Dong CaoMicrosoft employee Saturday, January 30, 2010 2:15 AM
- Marked as answer by Dong CaoMicrosoft employee Tuesday, February 2, 2010 6:28 PM
- Unmarked as answer by Speedware Saturday, March 13, 2010 4:52 AM
- Marked as answer by Speedware Monday, March 15, 2010 1:40 PM
Saturday, January 30, 2010 2:15 AM -
Hi,
I assume that you didn't see this COM exception with the original sample for the same batching setting and the number of records. There is a new MSDN sample for syncing SQL Server and SQL Express: http://code.msdn.microsoft.com/Release/ProjectReleases.aspx?ProjectName=sync&ReleaseId=3762. Instead of modifying the SQL Server with SQLCE sample, can you use new sample instead? Let us know if you get same repro with the new sample still.
For the COM exception, I don't know how you modified the original sample. Did you change it to a MTA application? The original sample is a UI app and run as STA. If you ran your sync in different thread with mismatch thread apartment model, you will hit this COM exception as you has found out.
Also, did you enable Reliable Messaging in your changes? In this case, you need to create your provider and start sync in a MTA thread if your app is not MTA.
Thanks,
Dong
This posting is provided AS IS with no warranties, and confers no rights.
I did not modify the apartment model. It is still STA. And I thought that the sample application uses reliable sessions (you said messaging, I assume you meant sessions) because it is a requirement of the contract (at least from my memory). Anyway, here is some more information...
This exception is not limited to the example I modified. My opinion is that whenever certain WCF faults occur, then the local proxy (the object created by the ChannelFactory) causes this exception to be thrown. I believe that my original problem was because of the WCF binding setting <readerQuotas maxArrayLength="1000000" /> which was set much lower per the test example. Other causes are issues with maxReceivedMessageSize, MaxSession and a number of others parameters. Whenever one of these conditions is violated within the WCF session, the remote endpoint sends a fault and this causes the exception.
In my experience over the last month, it strikes me that a remote end point hosted in IIS 6.0 is more stable that a self-hosted service but that is a anecdotal not quantative. As you get your WCF configuration better configured, you cut out the occurrence of this fault.
I do not believe that this is definitively answered and I will unmark it as answered.
FWIW, if you look at WCF traces you can see there are a number of threads running so there are possibilities for cross-thread issues.- Edited by Speedware Saturday, March 13, 2010 4:57 AM Added comment on reliable sessions..
Saturday, March 13, 2010 4:51 AM -
Hi,
...
you need to create your provider and start sync in a MTA thread if your app is not MTA.
Thanks,
Dong
This posting is provided AS IS with no warranties, and confers no rights.
Dong,
How would I do that? The GUI needs STA, so how do I start the sync in a MTA thread?- Proposed as answer by Lavanyr Monday, October 25, 2010 2:30 PM
Saturday, March 13, 2010 5:06 AM -
hi steve,
can you try this?
Thread t = new Thread(syncThread);
bool result = t.SetApartmentState(ApartmentState.MTA);
public static void syncThread()
{
//do all sync stuff here
}
Sunday, March 14, 2010 3:34 PM -
June,
I did something similar - I used BackgroundWorker because it is a cleaner way of doing this. All of my sync stuff is in a library that the application calls evently using someObjectName.Synchronize(); So, conceptually I have the following:
- Create the background worker
- Initialize it, hook events
- Disable the UI
- Start the thread going.
- The DoWork consists of all of the sync stuff with my library API, but this is where the sync stuff goes.
- The ProgressChanged event is optional. It could be used to update a progress bar.
- The RunWorkerCompleted event could display statistics and would then reenable the UI.
The net result of putting this in a separate thread is now the exception that started this post is displayed for what it is, namely a WCF fault. On my WCF connection, that can be by WCF itself, or by the remote service (where the remote provider is running) and so it could be the remote provider too. At least now the issue is solved.
Steveprivate void BackgroundSynchronize_Start() { this._backgroundSynchronize = new BackgroundWorker(); this._backgroundSynchronize.DoWork += new DoWorkEventHandler(this.BackgroundSynchronize_DoWork); this._backgroundSynchronize.ProgressChanged += new ProgressChangedEventHandler(this.BackgroundSynchronize_ProgressChanged); this._backgroundSynchronize.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.BackgroundSynchronize_RunWorkerCompleted); this.BackgroundSynchronize_DisableUI(); this._backgroundSynchronize.RunWorkerAsync(); } void BackgroundSynchronize_DoWork(object sender, DoWorkEventArgs e) { // do sync stuff } void BackgroundSynchronize_ProgressChanged(object sender, ProgressChangedEventArgs e) { // report on the progress } void BackgroundSynchronize_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { // Display the stats this.BackgroundSynchronize_DisplayStats(); // Re-enable the UI. this.BackgroundSynchronize_EnableUI(); }
Monday, March 15, 2010 1:40 PM