मैं एक जूनियर डेवलपर हूं जो सॉफ्टवेयर के लिए एक अद्यतन लिखने पर काम कर रहा है जो एक तृतीय-पक्ष समाधान से डेटा प्राप्त करता है, इसे एक डेटाबेस में संग्रहीत करता है, और फिर एक अन्य तृतीय-पक्ष समाधान द्वारा उपयोग के लिए डेटा को स्थिति देता है। हमारा सॉफ्टवेयर विंडोज सेवा के रूप में चलता है।
पिछले संस्करण के कोड को देखते हुए, मैं इसे देखता हूं:
static Object _workerLocker = new object();
static int _runningWorkers = 0;
int MaxSimultaneousThreads = 5;
foreach(int SomeObject in ListOfObjects)
{
lock (_workerLocker)
{
while (_runningWorkers >= MaxSimultaneousThreads)
{
Monitor.Wait(_workerLocker);
}
}
// check to see if the service has been stopped. If yes, then exit
if (this.IsRunning() == false)
{
break;
}
lock (_workerLocker)
{
_runningWorkers++;
}
ThreadPool.QueueUserWorkItem(SomeMethod, SomeObject);
}
तर्क स्पष्ट लगता है: थ्रेड पूल में कमरे के लिए प्रतीक्षा करें, सुनिश्चित करें कि सेवा बंद नहीं की गई है, फिर थ्रेड काउंटर को बढ़ाएं और काम को कतारबद्ध करें। एक बयान है कि तब कॉल के _runningWorkers
अंदर SomeMethod()
अंदर decremented है ।lock
Monitor.Pulse(_workerLocker)
मेरा प्रश्न यह
है कि क्या किसी एक के अंदर सभी कोड को समूहीकृत करने में कोई लाभ है lock
, जैसे:
static Object _workerLocker = new object();
static int _runningWorkers = 0;
int MaxSimultaneousThreads = 5;
foreach (int SomeObject in ListOfObjects)
{
// Is doing all the work inside a single lock better?
lock (_workerLocker)
{
// wait for room in ThreadPool
while (_runningWorkers >= MaxSimultaneousThreads)
{
Monitor.Wait(_workerLocker);
}
// check to see if the service has been stopped.
if (this.IsRunning())
{
ThreadPool.QueueUserWorkItem(SomeMethod, SomeObject);
_runningWorkers++;
}
else
{
break;
}
}
}
ऐसा लगता है, यह अन्य थ्रेड्स के लिए थोड़ा और इंतजार कर सकता है, लेकिन फिर ऐसा लगता है कि एक लॉजिकल ब्लॉक में बार-बार लॉक करना भी कुछ समय लेने वाला होगा। हालाँकि, मैं मल्टी-थ्रेडिंग में नया हूँ, इसलिए मैं मान रहा हूँ कि यहाँ अन्य चिंताएँ हैं जिनसे मैं अनजान हूँ।
केवल अन्य स्थान जहां _workerLocker
लॉक हो जाता है SomeMethod()
, और केवल डिक्रिप्टिंग के उद्देश्य से है _runningWorkers
, और फिर लॉग आउट करने और लौटने से पहले शून्य पर जाने foreach
की संख्या के _runningWorkers
लिए प्रतीक्षा करना है ।
किसी भी मदद के लिए धन्यवाद।
EDIT 4/8/15
अर्धविराम का उपयोग करने के लिए सिफारिश के लिए @delnan का धन्यवाद। कोड बन जाता है:
static int MaxSimultaneousThreads = 5;
static Semaphore WorkerSem = new Semaphore(MaxSimultaneousThreads, MaxSimultaneousThreads);
foreach (int SomeObject in ListOfObjects)
{
// wait for an available thread
WorkerSem.WaitOne();
// check if the service has stopped
if (this.IsRunning())
{
ThreadPool.QueueUserWorkItem(SomeMethod, SomeObject);
}
else
{
break;
}
}
WorkerSem.Release()
अंदर कहा जाता है SomeMethod()
।
SomeMethod
असिंक्रोनस रूप से कॉल करता है , ऊपर दिया गया "लॉक" अनुभाग नए थ्रेड के SomeMethod
चलने से पहले या कम से कम शीघ्र ही छोड़ दिया जाएगा ।
Monitor.Wait()
ताला जारी करने और पुन: प्राप्त करने का उद्देश्य एक और संसाधन है (इसलिए SomeMethod
, इस मामले में) इसका उपयोग कर सकते हैं। दूसरे छोर पर, SomeMethod
लॉक प्राप्त करता है, काउंटर को घटाता है, और फिर कॉल करता है Monitor.Pulse()
जो प्रश्न में विधि को लॉक लौटाता है। फिर, यह मेरी अपनी समझ है।
Monitor.Wait
ताला जारी किया। मैं डॉक्स पर एक नजर डालने की सलाह देता हूं।