Я хотел бы сгенерировать от 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