System.IO.IOException:'进程无法访问文件'@ .txt',因为它正由另一个进程使用。

时间:2017-07-01 07:35:23

标签: c# concurrency ioexception

我是编程的新手,我有一个问题。如果我有两个函数,一个创建一个文本文件并写入其中,而另一个打开相同的文本文件并从中读取。

我得到的错误是:

  

System.IO.IOException:'进程无法访问文件'@ .txt'   因为它正被另一个进程使用。'

我尝试为每个功能设置单独的计时器,但它仍然无效。我认为最好的方法是函数2在函数1结束之前不会启动。

你可以帮助我实现这个目标吗? 非常感谢你! 麦克

源代码:

public Form1() {
    InitializeComponent();
    System.Timers.Timer timerButtona1 = new System.Timers.Timer();
    timerButtona1.Elapsed += new ElapsedEventHandler(tickTimera1);
    timerButtona1.Interval = 3003;
    timerButtona1.Enabled = true;
}

private async void tickTimera1(object source, ElapsedEventArgs e) {
    function1();
    function2();
}

void function1() {
    List<string> linki = new List<string>();

    linki.Add("https://link1.net/");
    linki.Add("https://link2.net/");
    linki.Add("https://link3.net/");

    List<string> fileNames = new List<string>();

    fileNames.Add("name1");
    fileNames.Add("name2");
    fileNames.Add("name3");

    for (int x = 0; x < fileNames.Count; x++) {
        GET(linki[x], fileNames[x]);
        //System.Threading.Thread.Sleep(6000);
    }
}

async void GET(string link, string fileName) {
    var ODGOVOR = await PRENOS_PODATKOV.GetStringAsync(link);
    File.WriteAllText(@"C:\Users\...\" + fileName + ".txt", ODGOVOR);
}

void function2() {
    string originalText = File.ReadAllText(@"C:\Users\...\fileName.txt", Encoding.Default);
    dynamic modifiedText = JsonConvert.DeserializeObject(originalText);
    //then i then i read from the same text files and use some data from it..
}

6 个答案:

答案 0 :(得分:4)

编辑后你必须关闭文件。

var myFile = File.Create(myPath);
//myPath = "C:\file.txt"
myFile.Close();
//closes the text file for eg. file.txt
//You can write your reading functions now..

关闭后,您可以再次使用它(用于阅读)

答案 1 :(得分:3)

在编写完文本文件后,应先关闭它,然后再继续执行第二个功能:

var myFile = File.Create(myPath);
//some other operations here like writing into the text file
myFile.Close(); //close text file
//call your 2nd function here

只是详细说明:

public void Start() {
    string filename = "myFile.txt";
    CreateFile(filename); //call your create textfile method
    ReadFile(filename); //call read file method
}

public void CreateFile(string filename) {
    var myFile = File.Create(myPath); //create file
    //some other operations here like writing into the text file
    myFile.Close(); //close text file
}

public void ReadFile(string filename) {
    string text;
    var fileStream = new FileStream(filename, FileMode.Open, 
    FileAccess.Read); //open text file
    //vvv read text file (or however you implement it like here vvv
    using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
    {
        text = streamReader.ReadToEnd();
    }
    //finally, close text file
    fileStream.Close();
}

关键是,在完成对文件的任何操作后,必须关闭FileStream。您可以通过myFileStream.Close()

执行此操作

此外,File.Create(filename)会返回FileStream个对象,然后您可以Close()

答案 2 :(得分:1)

实际上这不是关闭/处理流的问题,File.WriteAllTextFile.ReadAllText在内部执行此操作。

问题是因为错误地使用了async/await模式。 GET是异步但从未等待过,因此导致function1完成并在所有内容实际写入文件之前转移到function2

编写GET的方式是不可接受的,因为它是async void,除非你处理事件或者真的知道你在做什么,否则永远不应该使用它。

因此,要么完全删除使用async/await,要么一直async

  1. GET更改为等待:

    async Task GET(string link, string fileName)
    
  2. 在现在的async function1

    中等待它
    async Task function1()
    {
        ...
        for (int x = 0; x < fileNames.Count; x++)
        {
            await GET(linki[x], fileNames[x]);
            //System.Threading.Thread.Sleep(6000);
        }
        ...
    
  3. function1事件中等待Elapsed

    private async void tickTimera1(object source, ElapsedEventArgs e)
    {
        await function1();
        function2();
    }
    

答案 3 :(得分:0)

问题是有时文件锁在关闭后不会立即释放。

您可以尝试运行循环来读取文件。在循环内部放置一个try catch语句,如果文件读取成功则从循环中断开。否则,请等待几毫秒并尝试再次读取该文件:

string originalText = null;
while (true)
{
    try
    {
        originalText = File.ReadAllText(@"C:\Users\...\fileName.txt", Encoding.Default);
        break;
    }
    catch 
    { 
        System.Threading.Thread.Sleep(100);
    }
}

答案 4 :(得分:0)

在其中一个单元测试中,我必须创建一个临时文件,然后将其删除,然后出现上述错误。

没有一个答案有效。 有效的解决方案是:

var path = $"temp.{extension}";
        using (File.Create(path))
        {
        }


        File.Delete(path);

答案 5 :(得分:-1)

创建一个文件,然后将其关闭。之后可以将数据保存到该文件中。 我做了如下。

if (!File.Exists(filePath))
{
    File.Create(filePath).Close();
}
File.WriteAllText(filePath, saveDataString)