现在的位置: 首页 > 综合 > 正文

日志 20071220(数组操作,File IO,using,TransactionScope)

2012年09月14日 ⁄ 综合 ⁄ 共 3311字 ⁄ 字号 评论关闭
这两天写程序写的头昏脑涨,连日志几乎都没时间写了......

1.昨晚在对一个Array做处理的时候,为了删除一个元素,写出了如代码段1非常臃肿的代码:

//代码段1

bool isFind = false//内存对象里是否包含待删除元素
foreach (FilesFile tempFile in contentInMemory.Items)
{
if (tempFile.Digest != file.Digest)
{
    newArray[count] 
= tempFile;
    count
++;

    
if (count == newArray.Length)
    
break;
}

else
{
    isFind 
= true;
}

}


if (isFind)
{
    tempConfig.Items 
= newArray;
    
return;
}

else
    
return;

实际上,在数组本身不大的情况下(既不需要考虑起空间开销时),利用List<>和Array之间的转换就能写出简洁得多的代码,如代码段2:

//代码段2

List
<FilesFile> list = new List<FilesFile>(oldArray);
list.Remove(toDel);
contentInMemory.Items 
= list.ToArray();

2.对于写文件,自己以前没有太注意过。潜意识里觉得,File.Open()方法实现应该是这样的:尝试去获取文件句柄,如果获取不到(正在被别的线程以互斥方式使用),当前线程睡眠一段时间之后再去尝试。写了代码段3一试,并非如此:

//代码段3

public class Even
{
     
public static void Main(string[] args)
    
{
        
string path = @"E:\Temp\CommonTest\coffee.jpg";
        File.Open(path, FileMode.Open, FileAccess.Write, FileShare.None);
        
        Thread t 
= new Thread(new ThreadStart(TryRead));
        t.Start();
        Thread.Sleep(
5000);
        Console.Read();
    }


    
public static void TryToRead()
    
{
        
string path = @"E:\Temp\CommonTest\coffee.jpg";
        FileInfo info 
= new FileInfo(path);
        
try
        
{
            FileStream stream 
= File.OpenRead(path);
            Console.WriteLine(stream.ReadByte());
        }

        
catch (Exception e)
        
{
            Console.WriteLine(e.StackTrace);
        }


        Console.Read();
    }

}

你会看到一个IOException被立刻抛出来。leafyang说得对,“谁知道那个文件会被占用到什么时候”,那么你要读写一个文件的时候,只能自己多try了。自己在项目中使用了代码段4:

//代码段4:获取一个非共享的可读可写的文件句柄

public static FileStream GetNotShareReadWriteStream(string path)
{
    
if ((path == null|| (!File.Exists(path)))
        
return null;

    FileStream stream 
= null;
    
int tryCount = 0;
    
while (stream == null)
    
{
        
try
        
{
            tryCount
++;
            
if (tryCount > 10)
            
{
                
string info ="系统无法获取对文件{0}的写权限,请检查此文件的状态";
                MessageBox.Show(
string.Format(info, path));
                
return null;
            }

            stream 
= File.Open(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None);
            
return stream;
        }

        
catch
        
{
            Thread.Sleep(
50);
        }

    }

}

3.以前也写过类如
 using (SqlConnection conn = new SqlConnection(...)){}
   这样的代码,但其实没想过为什么这么写(汗一个)。事实上,using关键字被编译后的效果等同于一队try,catch,离开using作用域的时候会调用SqlConnection的Dispose方法。所以,这个关键字多用于像SqlConnection, FileStream之类的含有非托管资源的类型。如果你的一个自定义类型里打开了一些非托管资源,也可以让它实现IDisposeable接口,然后手工释放所有的资源。
   注意,这个Dispose()方法的调用是无条件的,也就是说,这个要被Dispose的对象可能并不是在using中构造的,如代码段5:

//代码段5

public class Even
{
    
public static void Main(string[] args)
    
{
        
string path = @"E:\Temp\CommonTest\coffee.jpg";
        Test t 
= new Test();

        TryDispose(t);

        Console.Read();
    }


    
public static void TryDispose(Test test)
    
{
        
using (test)//test并非在using内构造
        {
            test.DoSomething();
        }

    }

}


public class Test : IDisposable
{
    
public void DoSomething()
    
{
        Console.WriteLine(
"I'm doing!");
    }


    
public void Dispose()
    
{
        Console.WriteLine(
"I am disposed!");
    }

}

4.事务(TransactionScope)的局限
 刚才异想天开,想用类似代码段6的代码来保证内存对象和硬盘上文件内容的同步:

//代码段6

using (TransactionScope scope = new TransactionScope())
{
    
this.AddFileToMemory(this.configContent, toAdd);
    
this.AddFileToConfig(toAdd);

    scope.Complete();
}

这是起不到效果的,因为目前的事务支持仅限于数据库事务而已......
 

抱歉!评论已关闭.