Бих искал да генерирам от 1 до 0,1 милиона числа, за да получа уникален идентификатор за името на моя файл. За да постигна това, създадох едно статично свойство, като използвах заключване, както следва: -
private static readonly object objLock = new object();
private static int _statInt = 1;
private static string statInt
{
get
{
lock (objLock)
{
if (_statInt >= 100000)
{
_statInt = 1;
}
else
{
_statInt = _statInt + 1;
}
return "_" + _statInt.ToString();
}
}
}
Забележка Не искам да генерирам уникален идентификатор за изхвърляне, тъй като може да е дубликат или комбинация от дата и час [Опитах и двете, създаваше се дубликат]. И в моя случай, ако горният метод се провали след 0,1 милиона, това е файл за мен [Тъй като горният код ще използвам за уникално име на файл и файлът се създава в партида от около 5000 и след това се изтрива]
Първи въпрос Горната кодова нишка безопасна ли е?
Ако да, тогава моят втори и оригинален въпрос започва от тук: -
Просто пазя пълния код тук, за да разбера по-добре проблема: -
class Program
{
static void Main(string[] args)
{
_Interfaceupload obj = new _Interfaceupload();
for (int i = 0; i < 100000; i++)
{
Thread thrd = new Thread(obj.getFileNoDuplicate);
thrd.Start();
}
Console.ReadLine();
Dictionary<string, string> obj0 = _Interfaceupload.objDic;
Console.ReadLine();
}
}
class _Interfaceupload
{
private static readonly object objLock = new object();
private static int _statInt = 0;
private static string _fileName = "C:/TEST/vikas";
private static string _InitfileName = "C:/TEST/vikas";
private static string statInt
{
get
{
lock (objLock)
{
if (_statInt > 100000)
{
_statInt = 0;
}
else
{
_statInt = _statInt + 1;
}
return "_" + _statInt.ToString();
}
}
}
public static string stateDate
{
get
{
return "_" + DateTime.Now.Ticks.ToString() + "_" + System.Guid.NewGuid();
}
}
public static Dictionary<string, string> objDic = new Dictionary<string, string>();
public void getFileNoDuplicate()
{
try
{
//objDic.Add(_InitfileName + statInt, string.Empty);
// _fileName = _InitfileName + stateDate;
_fileName = _InitfileName + statInt;
objDic.Add(FileManager2.Write(_fileName, "txt", "hello", false), string.Empty);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
class FileManager2
{
public static string Write(string file, string ext, string data, bool overwrite)
{
return (string)OperateOnFile(file, ext, data, overwrite);
}
private static object OperateOnFile(string file, string ext,
string data, bool overWrite)
{
StreamReader sr = null;
StreamWriter sw = null;
string workingFile = null;
string dir = null;
try
{
workingFile = file + "." + ext;
if (overWrite == false && File.Exists(workingFile))
{
workingFile = (string)OperateOnFile(workingFile + System.Guid.NewGuid().ToString(), ext, data, overWrite);
}
else
{
dir = "C:/TEST/";
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
sw = new StreamWriter(File.Open(workingFile, FileMode.Create, FileAccess.Write, FileShare.None), Encoding.UTF8);
sw.Write(data);
}
return workingFile;
}
finally
{
if (sr != null)
sr.Close();
if (sw != null)
{
sw.Flush();
sw.Close();
}
}
}
}
(може да изисква следното namespaces
за включване)
using System.Threading;
using System.IO;
Втори въпрос: Когато го стартирам в конзолно приложение (.NET framework 4.5), за 0,1 милиона записа, изглежда, че файлът се дублира, тъй като получавам изключение „файлът се използва от друг процес“ , но ако първият код е безопасен за нишка, тогава той не трябва да създава дублиран идентификатор до 0,1 милиона. Какво не е наред тук, както го наричам? или проблемът с класа StreamWriter или кодът заобикаля нишката? не съм сигурен, моля за съвет.
Забележка Не мога да заключа File.Exists
метод.
Редактирано След коментара на MarvinSmit направи методите като нестатични
private string _fileName = "C:/TEST/vikas";
private string _InitfileName = "C:/TEST/vikas";
Също така премахна речника и го промени, както следва: -
public void getFileNoDuplicate()
{
try
{
//objDic.Add(_InitfileName + statInt, string.Empty);
// _fileName = _InitfileName + stateDate;
_fileName = _InitfileName + statInt;
FileManager2.Write(_fileName, "txt", "hello", false);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
След това също не проработи.
Решение
О, БОЖЕ МОЙ!! Разбрах виновника... проблем със следния ред код
_fileName = _InitfileName + statInt;
Премахнах този ред и директно го предадох на метода.
public void getFileNoDuplicate()
{
try
{
FileManager2.Write(_fileName + statInt, "txt", "hello", false);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Това беше луда грешка, създадох единичен екземпляр на класа и го предадох в нишката,
Оценявам коментара на Марвин,
"_fileName = _InitfileName + statInt; четенето без заключване, докато се записва по безопасен начин, може да доведе до дубликати."
той го забеляза много скоро, но по-късно и двамата тръгнахме в различна посока.
Благодаря за коментарите на всички тук
dictionary
(използвах го за отстраняване на грешки), а също така направих_fileName
и_InitfileName
като нестатични, не работи, така че бях написал същоThreadPool
клас и го бях проверил преди това, не работеше, но тъй като току-що сменихме тези променливи като нестатични, така че може да работи сега, позволете ми да опитам веднъж с помощта на ThreadPool - person vikas   schedule 30.04.2014_fileName
локален за метода, а не член на класа. Така ще имате:_fileName = _InitfileName + statInt;
- person Jim Mischel   schedule 30.04.2014statInt
е безопасно за нишки. Останалата част от вашия код страда от неразбиране на разликите между статичните полета, полетата на екземплярите и локалните променливи и следователно не е плашещо безопасен за нишки. - person Jim Mischel   schedule 30.04.2014_fileName
и_InitfileName
сега не са статични и дори аз също не използвам статичен екземпляр наDictionary
- person vikas   schedule 30.04.2014stateDate
, което също взех статичен, а също така има само две статични променливи сегаobjLock
и_statInt
- person vikas   schedule 30.04.2014