私は非常に複雑なプログラミングの問題を抱えているので、数分間我慢してください。
WPF(C#)でメディアプレーヤーを作成することにしましたが、ちょっとした問題にぶつかりました。
アプリケーションをシングルインスタンスにして、ユーザーがサーバーファイルをダブルクリックしたときに、プログラムが1回だけ実行され、すべてのファイルをキューに入れて再生できるようにします。
私はMicrosoftの単一インスタンスの実装を含むいくつかの方法を試しましたが、何かを考えて実装したように、自分で作成することを決定するまで、何も機能していないようでした(これはおそらくインターネット上のどこかにありましたが、表示されませんでした)
基本的に、名前付きミューテックスを使用して、複数のインスタンスが開かれないようにし、他のインスタンスに引数をファイルに書き込むように強制します。その後、ミューテックスを作成したインスタンスがファイルを読み取ります。言うまでもなく、これはパフォーマンスに関しては非常に効果的ではありませんが、とにかく、ここにMain()関数の実装があります。VS2010によって自動的に生成されたものが本当に好きではなかったので、このMain()も最初から作成されていることに注意してください。
static void Main(string[] args)
{
string[] arguments = new string[0];
handler g = new handler();
bool createdNew = false;
Mutex lolpaca = new Mutex(true, "lolpacamaximumtrolololololol", out createdNew);
if (createdNew)
{
if (args != null)
{
var MainWindow = new MainWindow();
var app = new Application();
app.Run(MainWindow);
lolpaca.ReleaseMutex();
lolpaca.Dispose();
}
else
{
Array.Resize(ref arguments, 1);
arguments[0] = args[0];
string line;
//nu mai arunca exceptii nenorocitule
while ((line = g.ReadArgs()) != null)
{
int old_size = arguments.Length;
Array.Resize(ref arguments, arguments.Length + 1);
arguments[old_size] = line;
}
var MainWindow = new MainWindow(arguments, arguments.Length);
var app = new Application();
app.Run(MainWindow);
lolpaca.ReleaseMutex();
lolpaca.Dispose();
}
if (File.Exists(path))
{
File.Delete(path);
}
}
else
{
Thread writer = new Thread(new ParameterizedThreadStart(g.WriteArg));
writer.Start(args);
writer.Join();
try
{
g.WriteArg(args);
}
catch (IOException e)
{
MediaPlayerFinal_GUI_new.ExceptionCatcher exp = new MediaPlayerFinal_GUI_new.ExceptionCatcher(e.Source);
exp.Show();
}
}
}
また、このクラスを使用してスレッド間の同期を試みています
public class handler
{
static string path = @"D:\playlist.txt";
static FileStream fs = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
string line;
string arg;
bool readerFlag = false;
public string ReadArgs()
{
try
{
lock (fs) // Enter synchronization block
{
if (!readerFlag)
{ // Wait until writer finishes
try
{
// Waits for the Monitor.Pulse in WriteArg
Monitor.Wait(fs);
}
catch (SynchronizationLockException)
{
}
catch (ThreadInterruptedException)
{
}
}
TextReader tr = new StreamReader(fs);
while ((line = tr.ReadLine()) != null)
{
arg = line;
}
tr.Close();
tr.Dispose();
}
/* fs.Close();
fs.Dispose();*/
readerFlag = false;
Monitor.Pulse(fs);
return arg;
}
catch (IOException e)
{
MediaPlayerFinal_GUI_new.ExceptionCatcher exp = new MediaPlayerFinal_GUI_new.ExceptionCatcher(e.Source);
exp.Show();
return null;
}
}
public void WriteArg(object args)
{
lock (fs)
{
try
{
if (readerFlag)
{
try
{
Monitor.Wait(fs); // Wait for the Monitor.Pulse in ReadArgs
}
catch (SynchronizationLockException)
{
}
catch (ThreadInterruptedException)
{
}
}
arg = Convert.ToString(args);
// FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.Read);
TextWriter tw = new StreamWriter(fs);
tw.WriteLine(args);
tw.Close();
tw.Dispose();
}
catch (IOException e)
{
MediaPlayerFinal_GUI_new.ExceptionCatcher exp = new MediaPlayerFinal_GUI_new.ExceptionCatcher(e.Source);
exp.Show();
}
}
/* fs.Close();
fs.Dispose();*/
readerFlag = true;
Monitor.Pulse(fs);
}
}
これで、基本的に、ダブルクリックされたファイルごとに、Main()関数の1つのインスタンスがWindowsによって作成されます。最初のインスタンスはミューテックスを制御し、やりたいことを何でも実行します。他のインスタンスは、引数をファイルに書き込む必要があります。
さて、問題:どうやら、スレッド(すべて)が正しく同期せず、IO例外が発生することがあります。try-catchブロックはまったく何もしないように見えるため、これらの例外が正確にスローされる場所がわかりません。実際、これはtry-catchが機能するよりも少し深いと思います。
では、ユーザーが多数のファイルをダブルクリックしたときに生成されるすべてのスレッドを同期するにはどうすればよいですか?この実装は、最大3つのダブルクリックファイルで正常に機能し、3つを超えるファイル(最大9でテスト済み)でも機能する場合があります(機能する場合と機能しない場合があります)。これまでインターネットで見つけたものは、同じアプリケーションのいくつかのインスタンスが独立して実行されていることを示しています。
例を挙げていただければ幸いです:)
ありがとうございました。