簡體   English   中英

Realm不適用於xUnite和.net核心

[英]Realm doesn’t work with xUnite and .net core

我在使用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());
        }
    }

我在不同的機器(Windows和Mac)上獲得了不同的異常,我嘗試使用InMemoryConfiguration創建Realm instace。 在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,但它也沒有用。

這個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;
}

雖然我花了一段時間才將其應用到我的解決方案中。 首先,我不是將上下文設置為null ,而是使用Nito.AsyncEx.AsyncContext。 因為否則自動更改不會通過線程傳播,因為域需要非空的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;
        }
    }

此外,這修復了許多失敗的單元測試。 但我仍然收到同樣的異常 - 從不正確的線程訪問Realm。 我不知道為什么,因為一切都設置正確。 然后我發現失敗的測試與我使用async realm api的方法有關,特別是realm.WriteAsync 經過一些挖掘后,我在領域文檔中找到了以下幾行。

如果設置了SynchronisationContext.Current ,則不會出現問題,但會導致WriteAsync再次在線程池上調度,這可能會創建另一個工作線程。 因此,如果您在線程中使用Current ,請考慮只調用Write而不是WriteAsync

在我的代碼中,沒有直接需要使用異步API。 我刪除並替換為同步Write ,所有測試再次變為綠色! 我想如果我發現自己確實需要使用異步API,因為某種大量插入,我要么模擬那個特定的API,要么用我自己的后台線程替換使用Task.Run而不是使用Realm的版。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM