web-dev-qa-db-ja.com

System.IO.IOException:「プロセスは別のプロセスで使用されているため、ファイル「@ .txt」にアクセスできません。」

プログラミングは初めてで、質問があります。 2つの関数がある場合、1つはテキストファイルを作成して書き込み、もう1つは同じテキストファイルを開いて読み取ります。

私が得るエラーは次のとおりです:

System.IO.IOException:「プロセスは別のプロセスで使用されているため、ファイル「@ .txt」にアクセスできません。」

各機能に個別のタイマーを設定しようとしましたが、まだ機能しません。最善の方法は、機能1が終了するまで機能2が開始しないことだと思います。

これを達成するのを手伝ってもらえますか?どうもありがとうございました!マイク

ソースコード:

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
Mike

編集後にファイルを閉じる必要があります。

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

それを閉じた後、あなたは再びそれを使用することができます(読むために)

5
rshah4u

テキストファイルを書き込んだ後、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()にできます。

4
Geoman Yabes

実際には、これはストリームのクローズ/破棄の問題ではありません。File.WriteAllTextおよびFile.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();
    }
    
2
Ofir Winegarten

問題は、ファイルロックが閉じられた直後に解放されない場合があることです。

ループを実行してファイルを読み取ることができます。ループ内にtry catchステートメントを配置し、ファイルの読み取りに成功するとループからブレークします。そうでない場合は、数ミリ秒待ってからファイルの読み取りを再試行してください。

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