【问题标题】:System.IO.IOException: 'The process cannot access the file '@.txt' because it is being used by another process.'System.IO.IOException: '进程无法访问文件'@.txt',因为它正被另一个进程使用。'
【发布时间】:2017-12-05 03:01:00
【问题描述】:

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

我得到的错误是:

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

我已经尝试为每个功能设置单独的计时器,但它仍然不起作用。我认为最好的方法是功能二直到功能一结束才开始。

你能帮我实现吗? 非常感谢! 迈克

源代码:

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..
}

【问题讨论】:

  • 显示你的源代码。
  • 释放所有对象.....
  • 可能是您在完成写入文件后并没有关闭文件。
  • 代码很长很乱。基本上一个函数将数据保存到文本文件,然后另一个函数进入并从文件中读取。整个过程一次又一次地重复。我的代码是初学者而且非常混乱。
  • 贴出函数的代码和出错的地方..

标签: c# concurrency ioexception


【解决方案1】:

您必须在编辑后关闭文件。

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)创建 2)打开 3)写/读 4)关闭。所以,我不明白为什么它不起作用..即使在你的第二个功能之后,即读取文本文件,你也必须关闭它。
【解决方案2】:

写完你的文本文件后,你应该先关闭它,然后再继续你的第二个函数:

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()

【讨论】:

  • 谢谢,我会调查并做出相应的调整。
  • 如果您正在使用的流必须传递给另一个库怎么办?我必须将我的 streamwriter 传递给 JsonTextWriter (Newtonsoft.Json) 来写出结果。
【解决方案3】:

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

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

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

【讨论】:

  • 我喜欢这种方法,但我会避免在这样的逻辑中使用 while(true)。如果在读取文件期间抛出任何错误,这将继续重试。因此,假设故障模式是系统的而不是随机的,这将创建一个无限循环。
  • 我喜欢这种方法,但我会避免在这样的逻辑中使用 while(true)。如果在读取文件期间抛出任何错误,这将继续重试。因此,假设故障模式是系统的而不是随机的,这将创建一个无限循环。
  • 感谢 Alexander,这就是我的问题的解决方案。
【解决方案4】:

其实这不是关闭/释放流的问题,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. Elapsed 事件中等待function1

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

【讨论】:

  • 您对代码中的重叠确实是正确的。但是,即使在同步代码中,我也看到了相同的文件正在使用的问题。
【解决方案5】:

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

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

【讨论】:

    【解决方案6】:

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

    所有答案均无效。 有效的解决方案是:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-05
      • 2015-12-07
      相关资源
      最近更新 更多