大家好,我想实现这样的一个需求:
随机生成一个目录名称,如果这个目录不存在,那么就创建,如果存在,就重新生成,直到目录不存在并生成为止,但是运行这段代码的线程可能有成千上万个,所以需要加锁,并且效率要尽可能高。
我是这样想的:判断目录是否存在、创建新的目录,这应该是一个原子操作。但是如果两个线程生成的不是同一个路径,那么它们就不应该互斥,只有在生成的目录名称完全相同时,才需要互斥。
例如:
线程1生成的path="C:\folder1"
线程2生成的path="C:\folder1"
由于线程1和线程2生成的路径相同,所以应该进行互斥操作,避免出错。
但是如果:
线程1生成的path="C:\folder1"
线程2生成的path="C:\folder2"
由于线程1和线程2生成的路径不相同,所以不需要进行互斥操作。
不知道如何实现该需求?或者应该使用哪个锁?
谢谢大家。
随机生成一个目录名称,如果这个目录不存在,那么就创建,如果存在,就重新生成,直到目录不存在并生成为止,但是运行这段代码的线程可能有成千上万个,所以需要加锁,并且效率要尽可能高。
我是这样想的:判断目录是否存在、创建新的目录,这应该是一个原子操作。但是如果两个线程生成的不是同一个路径,那么它们就不应该互斥,只有在生成的目录名称完全相同时,才需要互斥。
例如:
线程1生成的path="C:\folder1"
线程2生成的path="C:\folder1"
由于线程1和线程2生成的路径相同,所以应该进行互斥操作,避免出错。
但是如果:
线程1生成的path="C:\folder1"
线程2生成的path="C:\folder2"
由于线程1和线程2生成的路径不相同,所以不需要进行互斥操作。
不知道如何实现该需求?或者应该使用哪个锁?
谢谢大家。
解决方案 »
- 正则表达式问题
- DataGridView的DefaultCellStyle.Format的问题
- C#中的~ & | ^用途?
- C#写C++ dll的回调函数问题
- 如何在C#中调用多参数(全部是Input,两个以上)的存储过程?急!!
- 求问access中查询日期类型不匹配问题 ,在线等待
- 请教在自己写的程序中,根据鼠标的click事件获得当前鼠标激活的windows窗口的句柄
- 关于DateTime类型与GUID类型的赋值问题
- 请教平面控件设计
- .Net如何通过public key/private key实现对assembly的控制访问?
- 求大神解答:怎么在C#窗体上实现打开一个word文档显示在richTextBox控件上?
- IEnumerator对数组直接赋值的问题
string temppath;
//ToDo Something
lock (thisLock) {
if (Directory.Exists(temppath)) {
Directory.CreateDirectory(temppath);
}else{
//ToDo Something
}
}
}
谢谢。
此类型的任何公共 static(在 Visual Basic 中为 Shared) 成员都是线程安全的。但不保证所有实例成员都是线程安全的。http://msdn.microsoft.com/zh-cn/library/vstudio/system.io.directory%28v=vs.90%29.aspx
private void TryCreateFolder()
{
while (true) // 循环:直到创建目录成功之后才退出循环
{
// 生成路径
string path = GeneratePath();
lock(thisLock) // 加锁
{
// 如果目录已经存在,那么生成另一个路径
if (Directory.Exists(path))
{
continue;
}
else // 目录不存在,那么创建之后,退出
{
Directory.CreateDirectory(path);
return;
}
}
}
}由于生成目录算法GeneratePath()可以保证在99.99%的可能下,path是各不相同的,因此这里对所有的线程都加锁是不科学的。
我的想法是这样的,假设线程1生成了路径:"C:\folder1",而且运行到了lock{}里面,
如果线程2生成的路径也是"C:\folder1",那么线程2必须等待线程1运行完lock{}之后才能够执行lock{}代码。
如果线程2生成的路径和线程1生成的路径不一样,例如"C:\folder2",那么虽然线程1还没有执行完lock{}代码,线程2也可以执行lock{}里面的代码。
但如果某线程在Directory.Exists时返回了false,另一个线程却在之后立即创建了同名文件夹呢?Directory.CreateDirectory异常了。
不锁就抓异常吧
private void TryCreateFolder() {
// 循环:直到创建目录成功之后才退出循环
while (true) {
// 生成路径
string path = GeneratePath();
// 如果目录已经存在,那么生成另一个路径
if (Directory.Exists(path)) {
continue;
} else {
try { //目录不存在,那么成功创建之后,退出
Directory.CreateDirectory(path);
break;
} catch { //创建失败,重新生成另一个路径
continue;
}
}
}
}
{
Directory.CreateDirectory(path);
return;
}
捕获异常后continue;
没限制干脆Guid.NewGuid()吧,又省事又省力,try...catch...都免了
private void Foo(Object obj)
{
while (true)
{
Directory.CreateDirectory("c:\\1\\1");
}
} private void button1_Click(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Foo), null);
ThreadPool.QueueUserWorkItem(new WaitCallback(Foo), null);
ThreadPool.QueueUserWorkItem(new WaitCallback(Foo), null);
ThreadPool.QueueUserWorkItem(new WaitCallback(Foo), null);
ThreadPool.QueueUserWorkItem(new WaitCallback(Foo), null);
ThreadPool.QueueUserWorkItem(new WaitCallback(Foo), null);
ThreadPool.QueueUserWorkItem(new WaitCallback(Foo), null);
ThreadPool.QueueUserWorkItem(new WaitCallback(Foo), null);
ThreadPool.QueueUserWorkItem(new WaitCallback(Foo), null);
ThreadPool.QueueUserWorkItem(new WaitCallback(Foo), null);
ThreadPool.QueueUserWorkItem(new WaitCallback(Foo), null);
ThreadPool.QueueUserWorkItem(new WaitCallback(Foo), null);
}你给我搞一个异常试试
你的代码只是让我发觉,Directory.CreateDirectory不会在创建已有文件夹时报错,仅此而已。
你能保证在一个线程的Directory.Exists与Directory.CreateDirectory之间,不会插入另一个线程的Directory.CreateDirectory么?
......
线程x:Directory.Exists("c:\\1\\1")=false
线程y:Directory.Exists("c:\\1\\1")=false
线程x:Directory.CreateDirectory("c:\\1\\1")
线程y:Directory.CreateDirectory("c:\\1\\1")
......好吧,本该创建2个不同文件夹的2个线程,最终只创建了一个文件夹
for (int i = 0; i < 100; i++) {
Thread t = new Thread(o => {
Interlocked.Increment(ref j);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString() + ":" + j.ToString());
Thread.Sleep(1);
Interlocked.Increment(ref j);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString() + ":" + j.ToString());
});
t.Start();
}
Thread.Sleep(1000);
Console.ReadKey();
}
private static int j;去看看运行结果吧!