Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Npgsql在异步环境中无限期地锁定线程_C#_Multithreading_Postgresql_Npgsql_Orleans - Fatal编程技术网

C# Npgsql在异步环境中无限期地锁定线程

C# Npgsql在异步环境中无限期地锁定线程,c#,multithreading,postgresql,npgsql,orleans,C#,Multithreading,Postgresql,Npgsql,Orleans,我一直在努力寻找C#的流行Postgres库Npgsql的问题答案。我不确定这是否完全是Npgsql的问题,尽管我怀疑这是因为我的代码非常直截了当。我看到的问题是:当我有时调用Npgsql上的异步方法时,线程会被锁定。从我所知道的情况来看,这个问题是随机发生的。结果是,我在Microsoft Orleans环境中运行(这可能与找到解决方案有关),线程无限期锁定,从而使Orleans的一个工作线程无法处理工作。当我进行更多的Npgsql调用时,这些被锁定的线程会堆积起来,最终奥尔良系统会因为线程耗

我一直在努力寻找C#的流行Postgres库Npgsql的问题答案。我不确定这是否完全是Npgsql的问题,尽管我怀疑这是因为我的代码非常直截了当。我看到的问题是:当我有时调用Npgsql上的异步方法时,线程会被锁定。从我所知道的情况来看,这个问题是随机发生的。结果是,我在Microsoft Orleans环境中运行(这可能与找到解决方案有关),线程无限期锁定,从而使Orleans的一个工作线程无法处理工作。当我进行更多的Npgsql调用时,这些被锁定的线程会堆积起来,最终奥尔良系统会因为线程耗尽而阻塞

所以我真的不知道这个问题可能是什么,但是因为锁定总是在同一个方法中发生,而且它似乎发生在Npgsql的一些子例程中,我认为进一步研究Npgsql是公平的

这是我在奥尔良存储提供程序(处理系统持久层的特殊类)中使用的代码

这是ProtobufSQL类的源代码:

public class ProtobufSQL
{
    public static List<Tuple<string, object>> FlattenToSQLColumns(IMessage message, MessageDescriptor descriptor, string prefix = null)
    {
        var fields = descriptor.Fields.InDeclarationOrder();

        var columns = new List<Tuple<string, object>>();

        for (var i = 0; i < fields.Count; i++)
        {
            var field = fields[i];
            var columnName = field.Name.ToLower();

            if (field.Name == "id")
            {
                ByteString bytes = (ByteString)field.Accessor.GetValue(message);
                var uuid = new Guid(bytes.ToByteArray());
                columns.Add(new Tuple<string, object>("id", uuid));
            }
            else if (field.FieldType == FieldType.Message)
            {
                var embeddedDescriptor = field.MessageType;
                var embeddedMessage = field.Accessor.GetValue(message);
                if (field.IsRepeated)
                {
                    throw new Exception("Repeated complex types are not supported, create a foreign key reference in a new object instead.");
                }
                else
                {
                    columns.AddRange(FlattenToSQLColumns((IMessage)embeddedMessage, embeddedDescriptor, $"{columnName}."));
                }
            }
            else if (field.FieldType == FieldType.Group)
            {
                throw new Exception("Groups are not supported by ProtobufSQL.");
            }
            else
            {
                var columnValue = field.Accessor.GetValue(message);
                var key = prefix + columnName;
                if (field.IsRepeated)
                {
                    var enumerableColumnValue = columnValue as IEnumerable;
                    Type listTypeOf = enumerableColumnValue.GetType().GetGenericArguments()[0];
                    Type listType = typeof(List<>).MakeGenericType(listTypeOf);
                    dynamic valueList = Activator.CreateInstance(listType);
                    foreach (var item in enumerableColumnValue)
                    {
                        valueList.Add((dynamic)item);
                    }
                    columns.Add(new Tuple<string, object>(key, valueList.ToArray()));
                }
                else
                {
                    columns.Add(new Tuple<string, object>(key, columnValue));
                }
            }
        }

        return columns;
    }

    public static async Task<IMessage[]> DataReaderToType(Type type, DbDataReader reader)
    {
        var descriptor = (MessageDescriptor)type.GetProperty("Descriptor").GetValue(null);

        IList<IMessage> objects = new List<IMessage>();

        while (await reader.ReadAsync())
        {
            var obj = Activator.CreateInstance(type);
            TraverseDbRow(reader, descriptor, obj);
            objects.Add((IMessage)obj);
        }

        return objects.ToArray();
    }

    private static void TraverseDbRow(DbDataReader reader, MessageDescriptor descriptor, object obj, string prefix = null)
    {
        var fields = descriptor.Fields.InFieldNumberOrder();

        for (var i = 0; i < fields.Count; i++)
        {
            var field = fields[i];
            if (field.FieldType == FieldType.Message)
            {
                if (field.IsRepeated)
                {
                    // Repeated embedded types will be broken out into a separate table,
                    // so there's no need to handle them here.
                }
                else if (field.IsMap)
                {
                    throw new Exception("Maps are not yet supported by ProtobufSQL.");
                }
                else
                {
                    var embeddedDescriptor = field.MessageType;
                    var embeddedObj = Activator.CreateInstance(embeddedDescriptor.ClrType);
                    TraverseDbRow(reader, embeddedDescriptor, embeddedObj, $"{prefix}{field.Name}.");
                }
            }
            else if (field.FieldType == FieldType.Group)
            {
                throw new Exception("Groups are not supported by ProtobufSQL.");
            }
            else
            {
                var columnName = prefix + field.Name;
                try
                {
                    var columnValue = reader[columnName];
                    var propertyInfo = obj.GetType().GetProperty(field.Name, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

                    if (field.Name == "id")
                    {
                        var guid = (Guid)columnValue;
                        ByteString bytes = ByteString.CopyFrom(guid.ToByteArray());
                        propertyInfo.SetValue(obj, bytes);
                    }
                    else if (field.IsRepeated)
                    {
                        var repeated = propertyInfo.GetValue(obj);
                        var addRange = repeated.GetType().GetMethod("AddRange");
                        addRange.Invoke(repeated, new object[] { columnValue });
                    }
                    else if (field.IsMap)
                    {
                        throw new Exception("Maps are not yet supported by ProtobufSQL.");
                    }
                    else
                    {
                        propertyInfo.SetValue(obj, Convert.ChangeType(columnValue, propertyInfo.PropertyType));
                    }
                }
                catch (IndexOutOfRangeException e)
                {
                    // columnName was not present in the response
                }
            }
        }
    }
}
公共类ProtobufSQL
{
公共静态列表列(IMessage消息、MessageDescriptor描述符、字符串前缀=null)
{
var fields=descriptor.fields.InDeclarationOrder();
var columns=新列表();
对于(变量i=0;ipublic class ProtobufSQL
{
    public static List<Tuple<string, object>> FlattenToSQLColumns(IMessage message, MessageDescriptor descriptor, string prefix = null)
    {
        var fields = descriptor.Fields.InDeclarationOrder();

        var columns = new List<Tuple<string, object>>();

        for (var i = 0; i < fields.Count; i++)
        {
            var field = fields[i];
            var columnName = field.Name.ToLower();

            if (field.Name == "id")
            {
                ByteString bytes = (ByteString)field.Accessor.GetValue(message);
                var uuid = new Guid(bytes.ToByteArray());
                columns.Add(new Tuple<string, object>("id", uuid));
            }
            else if (field.FieldType == FieldType.Message)
            {
                var embeddedDescriptor = field.MessageType;
                var embeddedMessage = field.Accessor.GetValue(message);
                if (field.IsRepeated)
                {
                    throw new Exception("Repeated complex types are not supported, create a foreign key reference in a new object instead.");
                }
                else
                {
                    columns.AddRange(FlattenToSQLColumns((IMessage)embeddedMessage, embeddedDescriptor, $"{columnName}."));
                }
            }
            else if (field.FieldType == FieldType.Group)
            {
                throw new Exception("Groups are not supported by ProtobufSQL.");
            }
            else
            {
                var columnValue = field.Accessor.GetValue(message);
                var key = prefix + columnName;
                if (field.IsRepeated)
                {
                    var enumerableColumnValue = columnValue as IEnumerable;
                    Type listTypeOf = enumerableColumnValue.GetType().GetGenericArguments()[0];
                    Type listType = typeof(List<>).MakeGenericType(listTypeOf);
                    dynamic valueList = Activator.CreateInstance(listType);
                    foreach (var item in enumerableColumnValue)
                    {
                        valueList.Add((dynamic)item);
                    }
                    columns.Add(new Tuple<string, object>(key, valueList.ToArray()));
                }
                else
                {
                    columns.Add(new Tuple<string, object>(key, columnValue));
                }
            }
        }

        return columns;
    }

    public static async Task<IMessage[]> DataReaderToType(Type type, DbDataReader reader)
    {
        var descriptor = (MessageDescriptor)type.GetProperty("Descriptor").GetValue(null);

        IList<IMessage> objects = new List<IMessage>();

        while (await reader.ReadAsync())
        {
            var obj = Activator.CreateInstance(type);
            TraverseDbRow(reader, descriptor, obj);
            objects.Add((IMessage)obj);
        }

        return objects.ToArray();
    }

    private static void TraverseDbRow(DbDataReader reader, MessageDescriptor descriptor, object obj, string prefix = null)
    {
        var fields = descriptor.Fields.InFieldNumberOrder();

        for (var i = 0; i < fields.Count; i++)
        {
            var field = fields[i];
            if (field.FieldType == FieldType.Message)
            {
                if (field.IsRepeated)
                {
                    // Repeated embedded types will be broken out into a separate table,
                    // so there's no need to handle them here.
                }
                else if (field.IsMap)
                {
                    throw new Exception("Maps are not yet supported by ProtobufSQL.");
                }
                else
                {
                    var embeddedDescriptor = field.MessageType;
                    var embeddedObj = Activator.CreateInstance(embeddedDescriptor.ClrType);
                    TraverseDbRow(reader, embeddedDescriptor, embeddedObj, $"{prefix}{field.Name}.");
                }
            }
            else if (field.FieldType == FieldType.Group)
            {
                throw new Exception("Groups are not supported by ProtobufSQL.");
            }
            else
            {
                var columnName = prefix + field.Name;
                try
                {
                    var columnValue = reader[columnName];
                    var propertyInfo = obj.GetType().GetProperty(field.Name, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

                    if (field.Name == "id")
                    {
                        var guid = (Guid)columnValue;
                        ByteString bytes = ByteString.CopyFrom(guid.ToByteArray());
                        propertyInfo.SetValue(obj, bytes);
                    }
                    else if (field.IsRepeated)
                    {
                        var repeated = propertyInfo.GetValue(obj);
                        var addRange = repeated.GetType().GetMethod("AddRange");
                        addRange.Invoke(repeated, new object[] { columnValue });
                    }
                    else if (field.IsMap)
                    {
                        throw new Exception("Maps are not yet supported by ProtobufSQL.");
                    }
                    else
                    {
                        propertyInfo.SetValue(obj, Convert.ChangeType(columnValue, propertyInfo.PropertyType));
                    }
                }
                catch (IndexOutOfRangeException e)
                {
                    // columnName was not present in the response
                }
            }
        }
    }
}