我在使用xUnite和Net core运行领域时遇到问题。这是我要运行的非常简单的测试
public class UnitTest1
{
[Scenario]
public void Test1()
{
var realm = Realm.GetInstance(new InMemoryConfiguration("Test123"));
realm.Write(() =>
{
realm.Add(new Product());
});
var test = realm.All<Product>().First();
realm.Write(() => realm.RemoveAll());
}
}
我在尝试使用InMemoryConfiguration创建Realm实例的不同计算机(Windows和Mac)上遇到了不同的异常。 在Mac上,我收到以下异常
libc++abi.dylib: terminating with uncaught exception of type realm::IncorrectThreadException: Realm accessed from incorrect thread.
在Windows上,运行时出现以下异常
ERROR Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. at
System.Net.Sockets.NetworkStream.Read(Span1 destination) at
System.Net.Sockets.NetworkStream.ReadByte() at
System.IO.BinaryReader.ReadByte() at
System.IO.BinaryReader.Read7BitEncodedInt() at
System.IO.BinaryReader.ReadString() at
Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.LengthPrefixCommunicationChannel.NotifyDataAvailable() at
Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.TcpClientExtensions.MessageLoopAsync(TcpClient client, ICommunicationChannel channel, Action1 errorHandler, CancellationToken cancellationToken) Source: System.Net.Sockets HResult: -2146232800 Inner Exception: An existing connection was forcibly closed by the remote host HResult: -2147467259
我正在使用Realm 3.3.0和xUnit 2.4.1 我曾尝试将其降级为Realm 2.2.0,但也无法正常工作。
答案 0 :(得分:0)
此问题的解决方案在this Github帖子中找到
这段代码帮助我解决了问题
Realm GetInstanceWithoutCapturingContext(RealmConfiguration config)
{
var context = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
Realm realm = null;
try
{
realm = Realm.GetInstance(config);
}
finally
{
SynchronizationContext.SetSynchronizationContext(context);
}
return realm;
}
尽管我花了一些时间将其应用于我的解决方案。
首先,我正在使用Nito.AsyncEx.AsyncContext,而不仅仅是将上下文设置为null
。因为否则自动更改将不会通过线程传播,因为领域需要非空SynchronizationContext
才能使该功能正常工作。因此,就我而言,该方法看起来像这样
public class MockRealmFactory : IRealmFactory
{
private readonly SynchronizationContext _synchronizationContext;
private readonly string _defaultDatabaseId;
public MockRealmFactory()
{
_synchronizationContext = new AsyncContext().SynchronizationContext;
_defaultDatabaseId = Guid.NewGuid().ToString();
}
public Realm GetRealmWithPath(string realmDbPath)
{
var context = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(_synchronizationContext);
Realm realm;
try
{
realm = Realm.GetInstance(new InMemoryConfiguration(realmDbPath));
}
finally
{
SynchronizationContext.SetSynchronizationContext(context);
}
return realm;
}
}
此外,这修复了许多失败的单元测试。但是我仍然收到相同的异常-从不正确的线程访问领域。而且我不知道为什么,因为一切设置正确。然后,我发现失败的测试与我使用异步领域api的方法有关,尤其是realm.WriteAsync
。经过更多的挖掘之后,我在领域文档中找到了以下几行。
如果您设置了
SynchronisationContext.Current
没问题,但是 这将导致WriteAsync再次在线程池上分派 可能会创建另一个工作线程。因此,如果您在自己的计算机中使用Current
线程,请考虑仅调用Write
而不是WriteAsync
。
在我的代码中,不需要直接使用异步API。我删除并替换为同步Write
,所有测试再次变为绿色!我想我是否由于某种大容量插入而需要使用异步API的情况下,我要么模拟该特定API,要么使用Task.Run
而不是我自己的后台线程替换使用Realm的版本。