Microsoft Sync Framework:元数据存储副本已在使用中

Microsoft Sync Framework: Metadata Store Replica is Already in Use

一些平台信息 - 我正在使用 Visual Studio 2015、Windows 10 Pro 和来自 Nuget 的最新版本的 MS Sync Framework。

using Microsoft.Synchronization;
using Microsoft.Synchronization.Files;
using System.IO;

namespace SyncEngine_Test
{
    class Program
    {
        static void Main(string[] args)
        {
            string myDocsPath = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            string Dir1 = Path.Combine(myDocsPath, "Dir1");
            string Dir2 = Path.Combine(myDocsPath, "Dir2");
            string metadataPath = Path.Combine(myDocsPath, "Metadata");
            string tempDir = Path.Combine(myDocsPath, "Cache");
            string trashDir = Path.Combine(myDocsPath, "Trash");
            FileSyncScopeFilter filter = new FileSyncScopeFilter();
            filter.FileNameExcludes.Add("*.metadata");
            FileSyncOptions options = FileSyncOptions.None;

            //DetectChanges
            DetectChangesOnFileSystemReplica(Dir1, filter, options, Dir1, "filesync.metadata", tempDir, trashDir);
            DetectChangesOnFileSystemReplica(Dir2, filter, options, Dir2, "filesync.metadata", tempDir, trashDir);

            //SyncChanges Both Ways
            SyncFileSystemReplicasOneWay(Dir1, Dir2, filter, options, Dir1, "filesync.metadata", tempDir, trashDir);
            SyncFileSystemReplicasOneWay(Dir2, Dir1, filter, options, Dir2, "filesync.metadata", tempDir, trashDir);
        }

        public static void DetectChangesOnFileSystemReplica(string replicaRootPath, FileSyncScopeFilter filter, FileSyncOptions options, string metadataPath, string metadataFile, string tempDir, string trashDir)
        {
            FileSyncProvider provider = null;
            try
            {
                provider = new FileSyncProvider(replicaRootPath, filter, options, metadataPath, metadataFile, tempDir, trashDir);
                provider.DetectChanges();
            }
            finally
            {
                // Release resources
                if (provider != null)
                    provider.Dispose();
            }
        }
        public static void SyncFileSystemReplicasOneWay(string sourceReplicaRootPath, string destinationReplicaRootPath, FileSyncScopeFilter filter, FileSyncOptions options, string metadataPath, string metadataFile, string tempDir, string trashDir)
        {
            FileSyncProvider sourceProvider = null;
            FileSyncProvider destinationProvider = null;
            try
            {
                sourceProvider = new FileSyncProvider(sourceReplicaRootPath, filter, options, metadataPath, metadataFile, tempDir, trashDir);
                destinationProvider = new FileSyncProvider(destinationReplicaRootPath, filter, options, metadataPath, metadataFile, tempDir, trashDir);

                destinationProvider.AppliedChange += new EventHandler<AppliedChangeEventArgs>(OnAppliedChange);
                destinationProvider.SkippedChange += new EventHandler<SkippedChangeEventArgs>(OnSkippedChange);

                SyncOrchestrator agent = new SyncOrchestrator();
                agent.LocalProvider = sourceProvider;
                agent.RemoteProvider = destinationProvider;
                agent.Direction = SyncDirectionOrder.Upload; // Sync source to destination
                Console.WriteLine("Synchronizing changes to replica: " + destinationProvider.RootDirectoryPath);
                agent.Synchronize();
            }
            finally
            {
                // Release resources
                if (sourceProvider != null) sourceProvider.Dispose();
                if (destinationProvider != null) destinationProvider.Dispose();
            }
        }
    }

我正在尝试编写自定义文件同步程序,但每当我尝试偏离 Microsoft 的默认示例时,我都会 运行 遇到问题。默认情况下,在检查更改和同步时,会在源和目标的根目录中创建一个名为 filesync.metadata 的文件。 FileSyncProvider 支持指定自定义元数据路径(不能为空)以及自定义 cache/trash 路径。这是我真正想要的,但我必须指定特定的元数据位置和文件名。

当我以这种方式 运行 时,我得到一个异常,即 元数据存储副本已在使用中 。当我在不同的文件夹中指定不同的名称、相同的名称,甚至是默认路径中的默认名称时,都会发生这种情况。这是我的代码示例:

我以前见过这个错误报告,但从来没有一个好的解决方案,这让我有点担心。我不知道我是否做错了什么,是否存在从未解决的框架问题,或者 Windows 10 是否是罪魁祸首。

同样,默认用法工作正常,但我无法设置自定义路径:

            // Default Implementation - WHICH WORKS
            // Explicitly detect changes on both replicas upfront, to avoid two change 
            // detection passes for the two-way sync

            DetectChangesOnFileSystemReplica(replica1RootPath, filter, options);
            DetectChangesOnFileSystemReplica(replica2RootPath, filter, options);

            // Sync in both directions

            SyncFileSystemReplicasOneWay(replica1RootPath, replica2RootPath, filter, options);
            SyncFileSystemReplicasOneWay(replica2RootPath, replica1RootPath, filter, options);

目前我愿意接受任何建议,甚至是 Microsoft Sync 的替代方案。感谢您的帮助!

好吧,有时您只需要走开就会意识到自己犯了一个非常愚蠢的疏忽。 SyncFileSystemReplicasOneWay() void 的创建方式导致我的 destinationProvider 使用完全相同的元数据 file/directory。我已经像这样修改了方法参数:

旧方法 - 行不通:

public static void SyncFileSystemReplicasOneWay(string sourceReplicaRootPath, string destinationReplicaRootPath, FileSyncScopeFilter filter, FileSyncOptions options, string metadataPath, string metadataFile, string tempDir, string trashDir){}

正确的方法 - 注意 BOTH 元数据文件的文件名和文件夹路径的添加:

public static void SyncFileSystemReplicasOneWay(string sourceReplicaRootPath, string destinationReplicaRootPath, FileSyncScopeFilter filter, FileSyncOptions options, string metadataPath1, string metadataFile1, string metadataPath2,string metadataFile2, string tempDir, string trashDir) {}

这是一个更大的片段,显示了源和目标提供者对象的创建:

    public static void SyncFileSystemReplicasOneWay(string sourceReplicaRootPath, string destinationReplicaRootPath, FileSyncScopeFilter filter, FileSyncOptions options, string metadataPath1, string metadataFile1, string metadataPath2, string metadataFile2, string tempDir, string trashDir)
    {
        sourceProvider = new FileSyncProvider(sourceReplicaRootPath, filter, options, metadataPath1, metadataFile1, tempDir, trashDir);
        destinationProvider = new FileSyncProvider(destinationReplicaRootPath, filter, options, metadataPath2, metadataFile2, tempDir, trashDir);
    }

所以我的粗心疏忽。至少它现在运行良好。