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);
}
所以我的粗心疏忽。至少它现在运行良好。
一些平台信息 - 我正在使用 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);
}
所以我的粗心疏忽。至少它现在运行良好。