أعمل مؤخرًا على تطبيق ConsoleApp لجدولة المهام. لن تناقش هذه المقالة جزء جدولة المهام في الوقت الحالي (سأكتب عنها لاحقًا).
متطلبات تشغيل ConsoleApp
1. ابدأ التطبيق عند بدء تشغيل النظام؛
2. مثيل واحد يعمل في كل جلسة؛
عند فتح رابط لسطح المكتب البعيد، يُسمح ببدء تشغيل مثيل واحد فقط من ConsoleApp.
3. يمكن تشغيل مثيل واحد فقط داخل النظام؛
عند فتح عدة روابط لسطح المكتب البعيد، يُسمح ببدء تشغيل مثيل واحد فقط من ConsoleApp.
موتيكس
Mutex: بدائية مزامنة يمكن استخدامها أيضًا للمزامنة بين العمليات.
MSND المرئي: http://msdn.microsoft.com/zh-cn/library/system.threading.mutex.aspx
وفي مقدمة الوثيقة الرسمية توجد هذه الفقرة
على خادم يقوم بتشغيل الخدمات الطرفية، يمكن أن يكون لكائن مزامنة النظام المسمى مستويين من الرؤية. إذا كان الاسم يبدأ بالبادئة "Global"، فسيكون كائن المزامنة مرئيًا في كافة جلسات عمل الخادم الطرفي. إذا كان الاسم يبدأ بالبادئة "Local"، فسيكون كائن المزامنة (mutex) مرئيًا فقط في جلسة الخادم الطرفي التي تم إنشاؤه فيها. في هذه الحالة، يمكن أن يكون لديك كائن مزامنة منفصل بنفس الاسم في كل جلسة خادم طرفية أخرى على الخادم. إذا تم إنشاء كائن مزامنة مسمى دون تحديد بادئة، فسيأخذ البادئة "Local". في جلسة خادم المحطة الطرفية، يكون اثنان من كائنات المزامنة التي تختلف فقط في بادئة الاسم الخاصة بهما هي كائنات المزامنة المستقلة، ويكون هذان الكائنان مرئيين لجميع العمليات في جلسة الخادم الطرفي. أي: تشير أسماء البادئات "Global" و"Local" إلى نطاق اسم كائن المزامنة (mutex) بالنسبة إلى جلسة الخادم الطرفي (وليس مرتبطًا بالعملية).
لسوء الحظ، لم يتم العثور على مثال C# ويمكن فهم هذا المقطع على النحو التالي.
mutexName= "Local\" +"AppName";
وهو صالح فقط للجلسة التي تم إنشاؤه فيها، مما يعني أنه عند فتح اتصال بعيد جديد، سيتم تشغيل مثيل ConsoleApp مرة أخرى.
mutexName= "Global\" +"AppName";
صالح لجميع الجلسات. عند فتح روابط بعيدة متعددة، فإن الرابط البعيد الأول فقط هو الذي سيبدأ تشغيل مثيل ConsoleApp بنجاح.
تشغيل كمثيل واحد لكل جلسة
الفراغ الثابت الخاص LocalMutex()
{
// ما إذا كان سيتم إنشاء كائن المزامنة (mutex) لأول مرة
bool newMutexCreated = false;
string mutexName = "Local\" + "tenghoo";
Mutex mutex = null;
يحاول
{
mutex = new Mutex(false, mutexName, out newMutexCreated);
}
قبض (استثناء على سبيل المثال)
{
Console.Write(ex.Message);
System.Threading.Thread.Sleep(3000);
بيئة.خروج(1);
}
// إنشاء كائن المزامنة لأول مرة
إذا (newMutexCreated)
{
Console.WriteLine("بدأ البرنامج");
// todo: هذه هي المهمة التي سيتم تنفيذها
}
آخر
{
Console.Write("هناك نافذة أخرى قيد التشغيل بالفعل وسيتم إغلاقها تلقائيًا بعد 3 ثوانٍ...");
System.Threading.Thread.Sleep(1000);
Console.Write("1");
System.Threading.Thread.Sleep(1000);
Console.Write("2");
System.Threading.Thread.Sleep(1000);
Console.Write("3");
Environment.Exit(1);// الخروج من البرنامج
}
}
عملية مثيل واحد على مستوى النظام
الفراغ الثابت الخاص GlobalMutex()
{
// ما إذا كان سيتم إنشاء كائن المزامنة (mutex) لأول مرة
bool newMutexCreated = false;
string mutexName = "Global\" + "tenghoo";
Mutex mutex = null;
يحاول
{
mutex = new Mutex(false, mutexName, out newMutexCreated);
}
قبض (استثناء على سبيل المثال)
{
Console.Write(ex.Message);
System.Threading.Thread.Sleep(3000);
بيئة.خروج(1);
}
// إنشاء كائن المزامنة لأول مرة
إذا (newMutexCreated)
{
Console.WriteLine("بدأ البرنامج");
// todo: هذه هي المهمة التي سيتم تنفيذها
}
آخر
{
Console.Write("هناك نافذة أخرى قيد التشغيل بالفعل وسيتم إغلاقها تلقائيًا بعد 3 ثوانٍ...");
System.Threading.Thread.Sleep(1000);
Console.Write("1");
System.Threading.Thread.Sleep(1000);
Console.Write("2");
System.Threading.Thread.Sleep(1000);
Console.Write("3");
Environment.Exit(1);// الخروج من البرنامج
}