Şu anda RFID kartları ile iletişim için Visual Studio 2012'de bir yazılım yazıyorum. Delphi'de kart okuyucusu ile iletişim kurmak için yazılmış bir DLL var.C# uygulama tüm sistemi donuyor
Sorun şu ki: Yazılımım VS2012 yüklü olan makinelerde düzgün çalışıyor. Diğer sistemlerde, kendisini veya tüm sistemi donduruyor. x32 ve x64 yapılandırması ile Win XP/7/8'de denedim. .NET 4.0 kullanıyorum.
Okuyucuya bağlandıktan sonra, yazılım okuyucular RF alanında envanter kartlarına bir komutla okuyucuyu (200 ms hızında) seçen bir backgroundWorker'ı başlatır. Çarpışma genellikle ca. Okuyucu bağlandıktan 10 ila 20 saniye sonra. DLL Delphi ile yazılmış
public String getCardID()
{
if (isConnectet())
{
IntPtr UIDs = IntPtr.Zero;
int len = 2 * 8;
Byte[] zero = new Byte[len];
UIDs = Marshal.AllocHGlobal(len);
Thread.Sleep(50);
Marshal.Copy(zero, 0, UIDs, len);
int count = 0;
int erg;
String ret;
try
{
erg = inventory(len, ref count, UIDs, 50);
}
catch (ExternalException) // this doesn't catch anything (iI have set <legacyCorruptedStateExceptionsPolicy enabled="true"/>)
{
return "\0";
}
finally
{
ret = Marshal.PtrToStringAnsi(UIDs, len);
IntPtr rslt = LocalFree(UIDs);
GC.Collect();
}
if (erg == 0)
return ret;
else
return zero.ToString();
}
else
return "\0";
}
[DllImport("tempConnect.dll", CallingConvention = CallingConvention.StdCall)]
private static extern int inventory(int maxlen, [In] ref int count,
IntPtr UIDs, UInt32 HFOffTime);
, kod DLL komut: İşte kod yerde bir bellek sızıntısı olabilir düşünüyorum
function inventory (maxlen: Integer; var count: Integer;
UIDs: PByteArray; HFOffTime: Cardinal = 50): Integer; STDCALL;
ama hiçbir fikrim yok
: ...DÜZENLEME bulmak için nasılYukarıdaki koduma bazı fikirler (açık GC.Collect(), try-catch-nihayet) ekledim, ancak hala çalışmıyor.
if (!bgw_inventory.IsBusy)
bgw_inventory.RunWorkerAsync();
Async backgroundworker yapar:
private void bgw_inventory_DoWork(object sender, DoWorkEventArgs e)
{
if (bgw_inventory.CancellationPending)
{
e.Cancel = true;
return;
}
else
{
String UID = reader.getCardID();
if (bgw_inventory.CancellationPending)
{
e.Cancel = true;
return;
}
if (UID.Length == 16 && UID.IndexOf("\0") == -1)
{
setCardId(UID);
if (!allCards.ContainsKey(UID))
{
allCards.Add(UID, new Card(UID));
}
if (readCardActive || deActivateCardActive || activateCardActive)
{
if (lastActionCard != UID)
actionCard = UID;
else
setWorkingStatus("OK", Color.FromArgb(203, 218, 138));
}
}
else
{
setCardId("none");
if (readCardActive || deActivateCardActive || activateCardActive)
setWorkingStatus("waiting for next card", Color.Yellow);
}
}
}
DÜZENLEME
aksiyon, her 200ms çalıştırır: Burada
getCardID() çağrıları koddurTi Şimdi kodda bazı küçük reworks (güncellemeler) yaptım. Şimdi sadece App. "tempConnect.dll" de 0xC00000FD (Yığın taşması) ile kilitleniyor. Bu, VS2012 yüklü Sistemlerde veya DLL'yi yerel Delphi ile kullanırsam gerçekleşmez! Başka bir fikri olan var mı?
DÜZENLEME Şimdi bunun yığıt var günlüğü DLL yapılan ve garip bir şey buldum: o denilen ve benim C# Programm çağrılan geçtiyse , yığıt yukarı ve aşağı sürekli değişiyor. Eğer doğal bir Deplhi Programından aynısını yaparsam, stacksize sabittir! Yani daha fazla araştırma yapacağım, ama gerçekten bir fikrim yok, ne aramam gerekiyor ...
Sadece bir şüpheniz, bunun sizin sorununuzunuzla ilgili olduğunu sanmıyorum, fakat 'inventory()' işlevini çağırdıktan sonra kodu çözümlemeniz, UIDS'nin boş olmadığını kontrol ediyorsunuz. Bu yapı, UIDS değerinin "envanter" fonksiyonunun içinde null olarak ayarlanabileceğini göstermektedir. Eğer durum buysa - referans ile UIDS'i paslatmamalısınız? –
En içteki try-catch işleyicisine, 'Marshal.FreeHGlobal() 'çağrısına ulaşılmadan önce istisna yapıldığında mevcut kod sızabilir. Marshal.FreeHGlobal() 'ın çağrısının yapıldığı bir 'son' cümleciğine bu işleyiciye eklemenizi öneririm. Böylelikle, bir şeyler yanlış gitmiş olsa bile, tahsis edilen hafızanın serbest kalmasını sağlarsınız. Ayrıca, hata maddesinin yakalama maddesinin içinde günlüğe kaydedilmesini öneririm, çünkü şu anda 'zero.ToString()' dönüş değeri 'envanter() tarafından döndürülen meşru bir değer olup olmadığını anlayamazsınız. . –
Lütfen getCardID() 'yi çağıran kodu gönderir misiniz? Bunu sormamın nedeni, yalnızca envanterin() birden fazla iş parçacığı tarafından eşzamanlı olarak çağrılabilmesi olasılığının olmadığını doğrulamaktır. Eğer iş parçacığı güvenli olacak şekilde tasarlanmamışsa, bu, yaşadığınız donmaların bir nedeni olabilir. Şerefe! –