私は、あらゆる種類のアクセスからファイルをロックしながら、複数のファイル (5 ~ 10 など) に対して読み取りおよび書き込み操作を実行できるクラスを作成しようとしていました。ファイルにアクセスするたびに(読み取りまたは書き込みの場合は関係ありません)、同じ名前で拡張子が異なる新しいファイルが作成されるため、他のスレッド(異なるアプリケーションに属する)にロックが通知されます(例:message.msg -> ロックファイル message.lock が作成されました)。
アプリケーションのすべてのインスタンスは、独自のファイルに書き込み、他のすべてのアプリケーション ファイル (そのファイルを含む) を読み取ります。
残念ながら、このクラスを使用するアプリケーションのいくつかのインスタンス (3 ~ 4 など) を開始すると、最初は動作しているように見えても、数秒または数分で 1 つのスレッドのように見えます。ファイルの解放に失敗しました。もちろん、これはその特定のファイルを読み取ることができない他のスレッドもブロックします。
これは、すべてのアプリがフリーズすると、永続的な .lock ファイルが表示されるためです。
もちろん、ロックの有効期限を設定することもできます (このシナリオではおそらく機能します) が、なぜこれが起こっているのでしょうか? 私にはこのコードは合理的に見えますが、もちろん私はまだ初心者です...だから...私の比率に市長の欠陥はありますか?
(これの長さに怖がらないでください。これらは 2 つの機能だけであり、中央部分を除いてほとんど同じことを行います)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
namespace y3kMessenger
{
static class FileLockAccess
{
public static string[] readAllLines(string path)
{
bool isLocked = false;
string[] toReturn;
string lockPath = path.Replace(Global.msgExtension, Global.lockExtension);
StreamWriter w;
//locking ...
while (!isLocked)
{
if (!File.Exists(lockPath))
{
try
{
using (w = new StreamWriter(lockPath))
{
w.WriteLine(" ");
}
isLocked = true;
}
catch (Exception e) { }
}
Thread.Sleep(10);
}
//locked, proceed with read
toReturn = File.ReadAllLines(path);
//release the lock
while (isLocked)
{
try
{
File.Delete(lockPath);
}
catch (Exception e) { }
isLocked = false;
}
return toReturn;
}
public static void writeLine(string path, string text, bool append)
{
bool isLocked = false;
string lockPath = path.Replace(Global.msgExtension, Global.lockExtension);
StreamWriter w;
//locking ...
while (!isLocked)
{
if (!File.Exists(lockPath))
{
try
{
using (w = new StreamWriter(lockPath))
{
w.WriteLine(" ");
}
isLocked = true;
}
catch (Exception e) { }
}
Thread.Sleep(10);
}
//locked, proceed with write
using (w = new StreamWriter(path, append))
w.WriteLine(text);
//release the lock
while (isLocked)
{
try
{
File.Delete(lockPath);
}
catch (Exception e) { }
isLocked = false;
}
}
}
}
編集:議論への追加として、次のコードが機能するようです:
public static string[] readAllLines(string path)
{
bool done = false;
string[] toReturn = null;
while (!done)
{
try
{
toReturn = File.ReadAllLines(path);
done = true;
}
catch (Exception e)
{
Thread.Sleep(50);
}
}
return toReturn;
}
public static void writeLine(string path, string text, bool append)
{
bool done = false;
while (!done)
{
try
{
using (StreamWriter w = File.AppendText(path))
{
w.WriteLine(text);
}
done = true;
}
catch (Exception e)
{
Thread.Sleep(50);
}
}
}
したがって、問題はスレッドが行っていることにあるべきではありません (これらのメソッドによって公開されるインターフェイスは最初の 2 つと同じであるため、他には何も変更していません)。