比如说现在有两个进程Pr1 和 Pr2
它们在运行过程中,如果满足某个条件,就会弹出一个标题为 xxx 的窗体。
现在启动这两个进程。如果它们在同一时间满足那个条件,就会弹出两个 xxx 窗体,这个如何实现互斥啊?
请高手解答。现在尝试过的方案:
[DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern int FindWindow(string lpClassName, string lpWindowName);
while(FindWindow(null, "xxx") != 0)
{
Thread.Sleep(100);
Application.DoEvents();
}
new xxx().ShowDialog();这样写直接卡的不成样子。尝试过Sleep(1000),Sleep(10000)。但是时间越长。同时弹出来的可能性就越大。另外
,这段在UI里面,没在线程。希望高手能指点一条明路啊~
它们在运行过程中,如果满足某个条件,就会弹出一个标题为 xxx 的窗体。
现在启动这两个进程。如果它们在同一时间满足那个条件,就会弹出两个 xxx 窗体,这个如何实现互斥啊?
请高手解答。现在尝试过的方案:
[DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern int FindWindow(string lpClassName, string lpWindowName);
while(FindWindow(null, "xxx") != 0)
{
Thread.Sleep(100);
Application.DoEvents();
}
new xxx().ShowDialog();这样写直接卡的不成样子。尝试过Sleep(1000),Sleep(10000)。但是时间越长。同时弹出来的可能性就越大。另外
,这段在UI里面,没在线程。希望高手能指点一条明路啊~
static void Main()
{
bool bExist;
//判断程序是否运行
Mutex MyMutex=new Mutex(true,"OnlyRunOncetime",out bExist);
if(bExist)
{
Application.Run(new Form1());
MyMutex.ReleaseMutex();
}
else
{
MessageBox.Show("***已经运行!","信息提示",MessageBoxButtons.OK,MessageBoxIcon.Information);
}
}
A C# Framework for Interprocess Synchronization and Communication
2.3 Inter-Process Semaphores,
http://www.codeproject.com/KB/threads/csthreadmsg.aspx
[DllImport("kernel32",EntryPoint="CreateSemaphore", SetLastError=true,CharSet=CharSet.Unicode)]
internal static extern uint CreateSemaphore( SecurityAttributes auth, int initialCount, int maximumCount, string name);[DllImport("kernel32",EntryPoint="WaitForSingleObject", SetLastError=true,CharSet=CharSet.Unicode)]
internal static extern uint WaitForSingleObject( uint hHandle, uint dwMilliseconds );[DllImport("kernel32",EntryPoint="ReleaseSemaphore", SetLastError=true,CharSet=CharSet.Unicode)]
[return : MarshalAs( UnmanagedType.VariantBool )]
internal static extern bool ReleaseSemaphore( uint hHandle, int lReleaseCount, out int lpPreviousCount);
[DllImport("kernel32",EntryPoint="CloseHandle",SetLastError=true, CharSet=CharSet.Unicode)]
[return : MarshalAs( UnmanagedType.VariantBool )]
internal static extern bool CloseHandle(uint hHandle);public class ProcessSemaphore : ISemaphore, IDisposable
{
private uint handle;
private readonly uint interruptReactionTime; public ProcessSemaphore(string name) : this( name,0,int.MaxValue,500 ) {}
public ProcessSemaphore(string name, int initial) : this( name,initial,int.MaxValue,500) {}
public ProcessSemaphore(string name, int initial, int max, int interruptReactionTime)
{
this.interruptReactionTime = (uint)interruptReactionTime;
this.handle = NTKernel.CreateSemaphore(null, initial, max, name);
if(handle == 0)
throw new SemaphoreFailedException();
} public void Acquire()
{
while(true)
{ //looped 0.5s timeout to make NT-blocked threads interruptable. uint res = NTKernel.WaitForSingleObject(handle, interruptReactionTime);
try
{
System.Threading.Thread.Sleep(0);
}
catch(System.Threading.ThreadInterruptedException e)
{
if(res == 0)
{ //Rollback int previousCount;
NTKernel.ReleaseSemaphore(handle,1,out previousCount);
}
throw e;
}
if(res == 0)
return;
if(res != 258)
throw new SemaphoreFailedException();
}
} public void Acquire(TimeSpan timeout)
{
uint milliseconds = (uint)timeout.TotalMilliseconds;
if(NTKernel.WaitForSingleObject(handle, milliseconds) != 0)
throw new SemaphoreFailedException();
} public void Release()
{
int previousCount;
if(!NTKernel.ReleaseSemaphore(handle, 1, out previousCount))
throw new SemaphoreFailedException();
} #region IDisposable Member
public void Dispose()
{
if(handle != 0)
{
if(NTKernel.CloseHandle(handle))
handle = 0;
}
}
#endregion
}
I copied the source code from the web page--you can have a look, but it is in English. Semaphores in Chinese is called 信号量, maybe you can search about 进程 and 信号量 yourself."System.Threading.Thread.Sleep(0);//这句有什么意义啊?"
//looped 0.5s timeout to [b]make NT-blocked threads interruptable.[\b]
* 进程 and 信号量 are get from: type pin yin of the two words in Google/Baidu first, and copy the words from the results
System.Threading.Mutex mutex = new System.Threading.Mutex(true, "", out hasMutex);
if (hasMutex)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FrmMain());
}
else
{
MessageBox.Show("程序已经运行", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
Application.Exit();
}或
[DllImport("User32.dll")]
public static extern void SetForegroundWindow(IntPtr hwnd);
[DllImport("User32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
private const int WS_SHOWNORMAL = 3;
private static bool ExistRunningInstance()
{
Process currentProcess = Process.GetCurrentProcess();
Process[] procList = Process.GetProcessesByName(currentProcess.ProcessName);
foreach (Process proc in procList)
{
if (proc.Id != currentProcess.Id)
{
ShowWindowAsync(proc.MainWindowHandle, WS_SHOWNORMAL);
SetForegroundWindow(proc.MainWindowHandle);return true;
}
}return false;
}
[STAThread]
static void Main()
{
if (ExistRunningInstance())
{
Environment.Exit(1);
}
}
http://security.zdnet.com.cn/security_zone/2008/0901/1097472.shtmlC#中四种进程或线程同步互斥的控制方法(二)
http://security.zdnet.com.cn/security_zone/2008/0901/1097477.shtml
Mutex 互斥进程可以,但是现在的情况是 进程已经有互斥了,需要互斥的是进程中的窗体,如果这个窗体的标题一样,只是在不同进程中,怎么实现互斥?请前辈赐教。还有,海风兄说的判断下有没有这个窗体,我就是这么做的啊。我根据窗口的标题取它的句柄,如果 == 0,那就不存在窗体。然后弹出来。关键是在while()中,这个Sleep()做循环体的时候,小了占很多资源,大了就有可能判断失效,而且阻塞进程UI,还弹出多个 xxx 窗体来。还有什么途径或方式么?高手们,Help Me 啊。
Mutex 互斥进程可以,但是现在的情况是 进程已经有互斥了,需要互斥的是进程中的窗体,如果这个窗体的标题一样,只是在不同进程中,怎么实现互斥?请前辈赐教。还有,海风兄说的判断下有没有这个窗体,我就是这么做的啊。我根据窗口的标题取它的句柄,如果 == 0,那就不存在窗体。然后弹出来。关键是在while()中,这个Sleep()做循环体的时候,小了占很多资源,大了就有可能判断失效,而且阻塞进程UI,还弹出多个 xxx 窗体来。还有什么途径或方式么?高手们,Help Me 啊。
Mutex 互斥进程可以,但是现在的情况是 进程已经有互斥了,需要互斥的是进程中的窗体,如果这个窗体的标题一样,只是在不同进程中,怎么实现互斥?请前辈赐教。还有,海风兄说的判断下有没有这个窗体,我就是这么做的啊。我根据窗口的标题取它的句柄,如果 == 0,那就不存在窗体。然后弹出来。关键是在while()中,这个Sleep()做循环体的时候,小了占很多资源,大了就有可能判断失效,而且阻塞进程UI,还弹出多个 xxx 窗体来。还有什么途径或方式么?高手们,Help Me 啊。
海风兄又敷衍我~。谢谢如梦前辈。
最后我是把所有的进程设立为子进程,然后从主进程请求是否允许弹xxx,所有的判断到放在主进程。这样只有一个判断,就解决问题了。就是有点麻烦。可能大家没弄清楚,这里如果pr1的xxx弹出来了,pr2要想弹,就要等pr1的xxx关闭以后才能弹,所以用到了很费资源的递归。我就是想找一种想进程互斥Mutex 这个对象类似的能解决这个问题的方式,但是最后还是绕回去了。 谢谢大家 结贴给分