我手上有一個相當複雜的編程問題,請耐心等待幾分鐘。在同一程序的多個實例之間同步
我決定我想在WPF(C#)中創建一個媒體播放器,並且我遇到了一個泡菜。
我希望我的應用程序是單實例,這樣當用戶雙擊服務器文件時,程序將只運行一次並排隊所有文件進行播放。我試過了幾種方式來做到這一點,包括微軟的單實例實現,直到我決定創建我自己的,就像我在做某事並實現它(這可能是在互聯網上某處,但它沒有出現)
基本上,我使用一個命名互斥體來防止打開多個實例,並強制其他實例將它們的參數寫入一個文件,之後,創建互斥體的實例將讀取該文件。不用說,就性能而言,這是非常非常無效的,但無論如何,這裏是我對Main()函數的實現。 請注意,這個Main()也是從頭開始編寫的,因爲我不太喜歡VS2010自動生成的那個。
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);
}
}
現在,基本上每個雙次點擊文件,一個實例主的()函數是由Windows創建的。 第一個實例可以控制互斥鎖並繼續做它想做的任何事情。 其他實例必須將它們的參數寫入文件。
現在,問題: 顯然,線程(所有這些線程)沒有正確同步,有時我得到IO異常。 我不知道究竟在哪裏引發了這些異常,因爲try-catch塊似乎什麼都不做。事實上,我認爲這比嘗試捕捉會更有力。
那麼,我如何同步用戶雙擊大量文件時產生的所有線程呢?這個實現可以和最多3個雙擊文件一起工作,有時(注意,有時可以工作,其他時間則不可以)有3個以上的文件(最多測試9個)。 目前爲止,我沒有發現互聯網帳戶上的多個獨立運行的應用程序的實例。
這將是巨大的,如果你能給我一個例子:)
謝謝。
請勿將文件用於進程間通信。將filespec發送到WM_COPYDATA消息中的已經運行的實例,使用管道,使用TCP,幾乎除磁盤文件之外的任何東西。 – 2012-04-22 22:49:21
我如何與WPF中的贏取消息進行交互?只要我知道,WPF是否最好阻止你這樣做。 – 2012-04-23 08:13:17
不要在意:P – 2012-04-23 08:38:19