Несколько потоков, обращающихся к UniData из UniObjects.NET, выдают ошибку UNI RPC
Мы использовали UniObjects.NET без проблем, пока не начали использовать его с BizTalk, который является многопоточным продуктом. Проблема заключается в ошибке ниже. Эта ошибка возникает только во 2-м потоке (и, возможно, в 3-м, 4-м и т. Д.). 1-й поток подключается и может получать данные из UniData очень хорошо. Ошибка не говорит о многом, и поиск возвращает только один результат, не имеющий отношения к нашей конкретной проблеме. У кого-нибудь есть ответчик или он может указать мне правильное направление? Эта ошибка не включает пул подключений, и мы не используем пул подключений, поскольку это вызывает другие ошибки.
Следует также отметить, что во время отладки мы писали некоторый код, который каждый поток записывал бы в отдельный файл некоторую отладочную информацию. Сам процесс записи отладочной информации в файл заставил оба потока работать правильно. Я не верю, что это проблема синхронизации соединения (то есть одновременное открытие UniSession), так как он завершается неудачно только в момент одновременного доступа к файлу UniData (при условии, что это происходит одновременно).
Документ UniObjects.NET для используемой нами версии файла UniObjects.NET версии 2.2.3.7377 (май 2010 года). Версия UniData - 7.2.
ОБНОВЛЕНИЕ: также попытался с UniObjects.NET версии 2.2.5.7463, и это все еще вызывает то же исключение.
Внутреннее исключение: GetX - ошибка с файлом 'MYFILEX'. [IBM U2][UODOTNET - UNIRPC][ErrorCode=81004] Из RPC был запрошен аргумент недопустимого типа Исключение: Исключение Источник: MyBusinessObjects Целевой сайт: System.Collections.Generic.List`1[MyBusinessObjects.XResponse] GetX(System.Collections.Generic.List`1[MyBusinessObjects.Lookup]) Ниже приведена трассировка стека, которая определяет местоположение, где произошло исключение в MyBusinessObjects.Lookups.GetX(List`1 Lookups) в MyBusinessObjects.Integration.GetXResponses(XmlDocument xml, String header, String gheader) в Orchestrations.XProcess.segment1(StopConditions stopOn) в Microsoft.XLANGs.Core.SegmentScheduler.RunASegment(Сегмент s, StopConditions stopCond, Исключение и exp)
ОБНОВЛЕНИЕ: та же ошибка, связанная с чтением списков.
Внутреннее исключение: [IBM U2][UODOTNET - UNIRPC][ErrorCode=81004] Из RPC был запрошен аргумент недопустимого типа Тип исключения: UniRPCPacketException Источник: Класс UniRPCPacket Целевой сайт: Byte[] ReadByteArray(Int32) Следующее является трассировкой стека, которая идентифицирует местоположение, где произошло исключение в IBMU2.UODOTNET.UniRPCPMessage.ReadByteArray(Int32 и индекс) в IBMU2.UODOTNET.UniSelectList.ReadList() в IBMU2.UODOTNET.UniSelectList.ReadListAsStringArray() на MyBusinessObjects.Lookups.GetY() на MyBusinessObjects.Integration.GetResponses(XmlDocument xml, строковый заголовок, строковый gsheader) в Orchestrations.Process.segment1(StopConditions stopOn) в Microsoft.XLANGs.Core.SegmentScheduler.RunASegment(Сегменты s, StopConditions stopCond, Exception& exp)
1 ответ
Эта проблема решена. Теперь вы можете использовать последнюю версию UO.NET, и я надеюсь, что эта проблема решена. Вы также можете использовать новый программный продукт Rocket под названием "U2 Toolkit for .NET". Это интегрированное решение, содержащее функции ADO.NET, UO.NET и LINQ to Entity. Чтобы протестировать многопоточность, вы можете использовать следующий код (вместо BiZtalk Server). Мы использовали PLINQ и U2 Toolkit для.NET.
class Program
{
static int NumberofThreads = 20;
const string uniFileName = "PRODUCTS";
static UniFile file = null;
static UniSession session = GetUniSession();
// setup ok/error counters
static int ok = 0;
static int error = 0;
static void Main(string[] args)
{
// connect with no locks
session.BlockingStrategy = UniObjectsTokens.UVT_WAIT_LOCKED;
session.LockStrategy = UniObjectsTokens.UVT_NO_LOCKS;
session.ReleaseStrategy = UniObjectsTokens.UVT_WRITE_RELEASE;
Stopwatch watch = new Stopwatch();
watch.Start();
// take only 20 distinct record ids
List<string> recordIds = new List<string>(RecordIds());
// run as parallel
Parallel.ForEach(recordIds, x =>
{
try
{
// connect to UniData CM file
var file2 = session.CreateUniFile(uniFileName);
// read individual record id
file2.Read(x);
file2.Close();
Interlocked.Increment(ref ok);
Console.WriteLine("rec id:" + x);
}
catch (Exception ex)
{
Interlocked.Increment(ref error);
Console.WriteLine("Claim: {0}. Error: {1}", x, ex.Message);
}
});
// set count & setup threads
int count = 0;
watch.Stop();
// write error
Console.WriteLine("Time: {2}, Count: {3}, OK: {0}, Error: {1}", ok, error, watch.Elapsed, count);
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
static UniSession GetUniSession()
{
U2ConnectionStringBuilder conn_str = new U2ConnectionStringBuilder();
conn_str.UserID = "user";
conn_str.Password = "pass";
conn_str.Server = "localhost";
conn_str.Database = "XDEMO";
conn_str.ServerType = "UNIDATA";
conn_str.AccessMode = "Native"; // FOR UO
conn_str.RpcServiceType = "udcs"; // FOR UO
conn_str.Pooling = false;
string s = conn_str.ToString();
U2Connection con = new U2Connection();
con.ConnectionString = s;
con.Open();
Console.WriteLine("Connected.........................");
U2.Data.Client.UO.UniSession us1 = con.UniSession;
if (file == null)
{
file = us1.CreateUniFile(uniFileName);
}
return us1;
}
public static List<string> RecordIds()
{
List<string> lRECIDList = new List<string>();
UniSelectList sl = session.CreateUniSelectList(2);
// Select UniFile
UniFile fl = session.CreateUniFile("PRODUCTS");
sl.Select(fl);
bool lLastRecord = sl.LastRecordRead;
int lIndex = 0;
while (!lLastRecord)
{
string s4 = sl.Next();
lRECIDList.Add(s4);
//Console.WriteLine("Record ID:" + s4);
lLastRecord = sl.LastRecordRead;
lIndex++;
if (lIndex >= NumberofThreads)
{
break;
}
}
return lRECIDList;
}
}